微信朋友圈广告在哪里做,烟台优化网站公司哪家好,网站设计首页动态效果怎么做,阿里做外贸的网站侯捷课程笔记#xff08;一#xff09;#xff08;传统c语法#xff0c;类内容#xff09; 2023-09-03更新#xff1a; 本小节已经完结#xff0c;只会进行小修改 埋下了一些坑#xff0c;后面会单独讲或者起新章节讲 最近在学习侯捷的一些课程#xff0c;虽然其中大部…侯捷课程笔记一传统c语法类内容 2023-09-03更新 本小节已经完结只会进行小修改 埋下了一些坑后面会单独讲或者起新章节讲 最近在学习侯捷的一些课程虽然其中大部分内容之前也都已经了解过了不过还是收获颇丰特别是独立与所谓语法之外的还有许多与设计相关的。
这一章内容比较简单也就直接摆出内容吧 相关重点内容就提一提大部分都直接掠过了。然后会加入一些自己的侯捷没有讲到的内容。
那就直接开始吧 类设计时头文件防止重复包含
通常用法就是
#ifndef FOO_H__
#define FOO_H__
// ... 主体内容#endif // FOO_H__因为这个很常用但是每次都要写三行也就有了简化版本
#pragma once不过这个可能需要编译器支持大部分肯定都是没问题的 类内成员函数默认就是inline
inline就是内联inline允许我们在头文件中定义函数重复包含时而不会发生重复定义问题 由于很多时候我们写类是在头文件中声明在头文件这时候如果成员函数定义在类内不也就是把函数放在了头文件吗编译器比较智能也就默认给类内定义的成员函数自动加上了inline属性 如果我们要把类的成员函数写在类外就没有inline这个属性了这时候如果还在头文件我们就要手动加上inline了 类使用初始化列表对成员进行初始化
初始化列表其实也就只有两个需要注意的点
初始化的顺序不是按照写的顺序来的而是按照成员变量定义的顺序来的如果父类没有默认构造函数也就是子类必须显式调用函数初始化父类这时候也就必须要使用初始化列表初始化父类 类内对函数加上const常函数
正常的成员函数是可以更改类的所以对于一个const属性的类编译器考虑到这个类不可以更改也就不允许它调用普通的成员函数只能调用常函数带const属性的函数 一个良好的变成习惯是对于一些不会更改成员变量/类属性的函数都应该加上const属性比如获取变量GetVal类似的函数
ps使用const实例化一个对象这个类一定要有用户定义的构造函数 对于第一点比如下面的代码
struct A {int a;int b;A() : b(1), a(2) {}
};在这里初始化的顺序实际上是先执行a2再执行b1因为a是先定义的那个 看起来好像无所谓但是下面的代码
struct A {int a;int b;A() : b(1), a(b) {}
};就会出现a先初始化但是这时候b还没有初始化的问题 对于第二点比如
struct Base {int a;Base(int){}
};
struct Derive : public Base {Derive(){};
};父类没有默认的构造函数子类必须要也只能通过初始化列表初始化父类
struct Derive : public Base {Derive():Base(10){};
};对于一个类来说常用的构造函数或者基本架构是什么样的
在侯捷的课程中常写的是
构造函数析构函数拷贝构造函数拷贝赋值函数
其中如果类中包含指针常常会自己写拷贝构造和拷贝复制并会在析构函数中对指针进行处理
而在c11后引入右值的概念 增加了
移动构造函数移动复制函数
class MyClass {public:MyClass();MyClass(const MyClass ) default;MyClass(MyClass ) default;MyClass operator(const MyClass ) default;MyClass operator(MyClass ) default;~MyClass();
};类中使用友元和重载cout
我们通常会这么写并且也可以直接把重载函数写在类内
struct A {public:friend std::ostream operator(std::ostream os,const A obj) {os obj.a;return os;}private:int a;
};可以注意几点
加上friend就可以访问类中的私有变量输入的os没有加上const是因为os执行会更改内部内容无法使用const输入的引用是为了避免不必要的拷贝obj加上const是加上后也可以传入右值返回引用是可以使用链式编程 带有指针的类的结
如果类内带有指针比如类的构造函数里会new一块内存。
需要在析构函数内释放对应的内存需要注意深拷贝和浅拷贝的问题 拷贝构造函数和复制构造函数需要重写重新开辟内存来进行深拷贝 在赋值构造前需要注意是否是自身赋值自己赋值给自己需要判断这种特殊情况以防止bug
比如下面这个示例注意关注一下前面提到的几点
template typename T
struct A {public:A(int n) {size n;str new T[n];}~A() { delete[] str; }A(const A obj) { Copy(obj); }A operator(const A obj) {if (obj this) return *this;Copy(obj);return *this;}void Copy(const A obj) {if (str) delete[] str;size obj.GetSize();str new T[size];std::memcpy(str, obj.str, size * sizeof(T));}int GetSize() const { return size; }private:int size 0;T* str nullptr;
};内存分配和管理
这一部分其实单独属于一块内容后面会单独讲 设计模式单例模式或者其它
这一部分其实单独属于一块内容后面会单独讲 类转换成标准类型(operator int())
类可以使用operator转换成一些类型在编辑器认为转化可以通过编译时会进行转换当然我们也可以使用static_cast显式转化
struct A {public:A(int a_) { a a_; }int a;operator int() {return a;}operator float() {return a;}
}
void Test() {Aa(10);int b10static_castint(a);int cstatic_castfloat(a)100;
}需要注意的是这个operator函数并不需要返回值默认返回值类型就是你写的要转换的类型 这里operator不光可以转为内置类型int/float还可以转换成自己写的类等等
类通过单参数的构造函数自动转化/explicit
c可以通过operator将类转化成一些类型同样也支持反向转化编译器可以自动根据单参数输入的构造函数将对应的参数的自动执行构造函数构造对象 这里说的单参数只指可以输入是一个参数的函数比如一个函数有三个三数但是后面两个带了默认参数也满足单参数又或者只有一个参数并且这个参数是默认参数也属于单参数
struct A {public:A(int a_) { a a_;}int a;A operator(const A obj) {return A(aobj.a);}
};比如我要执行 A a(10); A ba10; 这里重载了运算符c会自动将后面的10调用构造函数转换成一个类 如果是A b10a就不行 这里的运算符属于内置的int在这里就不会默认转换 如果要运行这句话就要用前面的operator int() operator int() {return a;
}运行的顺序就是先把a转换成int然后10整数然后将加之后的结果转换成A类类型赋值给b 如果我们同时写了单参数的构造函数和operator 类型()就有可能出现冲突就比如上面的例子 struct A {public:A(int a_) { a a_;}int a;A operator(const A obj) {return A(aobj.a);}operator int() {return a;}
}void Test() {A a(10);A ba10;A c10a;
}这里的A ba10;就会有问题因为冲突了
因为既可以把10调用构造函数转换成类然后执行operator 也可以把a转换成int然后加了后再调用构造函数转换成类
这时候我们就可以使用explicit显式的禁止允许单参数的构造函数的默认转换这样那个构造函数就只允许我们显式调用而不允许转换了。在示例中也就是不允许10转换成类的类型了 让类表现出指针形式重载*和-
我们可以重载*和-让类表现出类似于指针的形式使用示例比如说智能指针和容器的迭代器
struct A {public:int operator*() const {return *p;}int* operator-() const {return (this-operator*());// return p;}int* p;
};在这里*用来表现解引用-用来表现指针的成员内容一般来说-在函数返回值表现形式后还会有一个潜在的-设计如此 让类表现出函数形式重载括号运算符
这个其实非常常用比如在ceres库中用于传递代价函数平时也把这种函数叫做仿函数模仿函数
struct A {public:template typename TT operator()(const T a,const T b) {return ab?a:b;}
};
void Test() {A a;std::cout a(10,20);
}函数模板/类模板/模板模板参数
对于模板来说关键字class和typename是一样的为啥有两个历史原因不重要了 函数模板
template typename T
void Foo(T t) {}类模板
template typename T
struct Foo {Foo(T t) {}
}模板模板参数
template typename T
struct Foo {T foo;
};template typename T,template typename class my_class
struct A {my_classT class_a;
};template typename T1,typename T2
struct Goo {T1 goo1;T1 goo2;
};
template typename T1,typename T2,template typename,typename class my_class
struct B {my_classT1,T2 class_b;
};void Test() {Aint,Foo a;Bint,float,Goo b;
}其中template typename class my_class是一个示例表示输入的是带有一个模板参数的类
template表示这是一个模板typename的个数表示对应类的模板个数需要和传入的模板类对应class 也是个关键词和typename一样换成typename也是可以的my_class是这个模板名
在上面的示例中分别给了一个参数和两个参数的模板类传参示例 模板特化和偏特化
其实特化也就是指定模板的某一个或者任意个参数。 所以特化也就分成全特化和偏特化全特化就是所有模板参数都指定的特化偏特化就是只指定部分的特化
有一条规则是函数模板只允许全特化不允许偏特化类模板允许偏特化
比如在c标准库中判断一个参数是否为整数的源码
// Integer types
template typename _Tp
struct __is_integer {enum { __value 0 };
};
template
struct __is_integerbool {enum { __value 1 };
};
template
struct __is_integerchar {enum { __value 1 };
};
template
struct __is_integersigned char {enum { __value 1 };
};
template
struct __is_integerunsigned char {enum { __value 1 };
};
...
后面有其它整数类型包括了int和long,都是和前面一样的
...在这里列出所有整数类型只要是整数就会进入到特化的版本这样只需要根据__value的值就可以判断了 上面这种形式就是全特化
再给个函数模板全特化的例子
template typename T1,typename T2
void Foo(T1 a,T2 b) {std::cout Test1 std::endl;
}template
void Fooint,float(int a,float b) {std::cout Test2 std::endl;
}void Test() {Fooint,int(10,20);Fooint,float(10,20);Foo(10,20);Foo(10,20.0f);
}下面演示下类模板的偏特化和全特化
template typename T1,typename T2
struct A {A(T1 a,T2 b) {std::cout A std::endl;}
};template typename T
struct Aint,T {A(int a,T b) {std::cout Aint,T std::endl;}
};template typename T
struct Afloat,T {A(int a,T b) {std::cout Afloat,T std::endl;}
};template
struct Aint,int {A(int a,int b) {std::cout Aint,int std::endl;}
};template
struct Aint,float {A(int a,float b) {std::cout Aint,float std::endl;}
};void Test() {A(10,20);A(10,20);A(10.0f,20);A(10,20);A(10,20.0f);
}在上面的例子中就是给了两个偏特化和两个全特化
通过前面的全特化都可以看出来全特化一般会伴随template 出现因为全都指定了也就没有T类型了 auto/右值引用/变长模板 等c11的内容
这些内容后面都会单独讲而且其中很多内容在c14/c17会有变化和增强 比如右值在c17后定义更加成熟变长模板增加了一些展开方式 后面单独讲比在这里粗浅的讲要好 继承/虚函数/虚表
这一块最好也是单独开一块内容来讲关于虚的内容还是很多的。底层实现也很值得研究。
文章转载自: http://www.morning.rrbhy.cn.gov.cn.rrbhy.cn http://www.morning.rbhqz.cn.gov.cn.rbhqz.cn http://www.morning.tdcql.cn.gov.cn.tdcql.cn http://www.morning.qprtm.cn.gov.cn.qprtm.cn http://www.morning.qxwwg.cn.gov.cn.qxwwg.cn http://www.morning.ftync.cn.gov.cn.ftync.cn http://www.morning.hsksm.cn.gov.cn.hsksm.cn http://www.morning.hrzhg.cn.gov.cn.hrzhg.cn http://www.morning.ljygq.cn.gov.cn.ljygq.cn http://www.morning.lbbrw.cn.gov.cn.lbbrw.cn http://www.morning.mrckk.cn.gov.cn.mrckk.cn http://www.morning.pzss.cn.gov.cn.pzss.cn http://www.morning.hcqd.cn.gov.cn.hcqd.cn http://www.morning.zstbc.cn.gov.cn.zstbc.cn http://www.morning.hwpcm.cn.gov.cn.hwpcm.cn http://www.morning.nrwr.cn.gov.cn.nrwr.cn http://www.morning.ctrkh.cn.gov.cn.ctrkh.cn http://www.morning.nzkkh.cn.gov.cn.nzkkh.cn http://www.morning.yuminfo.com.gov.cn.yuminfo.com http://www.morning.rshijie.com.gov.cn.rshijie.com http://www.morning.nmymn.cn.gov.cn.nmymn.cn http://www.morning.tdgwg.cn.gov.cn.tdgwg.cn http://www.morning.bsqkt.cn.gov.cn.bsqkt.cn http://www.morning.qgqck.cn.gov.cn.qgqck.cn http://www.morning.kjyqr.cn.gov.cn.kjyqr.cn http://www.morning.rpkl.cn.gov.cn.rpkl.cn http://www.morning.kbdjn.cn.gov.cn.kbdjn.cn http://www.morning.ygkq.cn.gov.cn.ygkq.cn http://www.morning.bmsqq.cn.gov.cn.bmsqq.cn http://www.morning.kwjyt.cn.gov.cn.kwjyt.cn http://www.morning.wcghr.cn.gov.cn.wcghr.cn http://www.morning.jzccn.cn.gov.cn.jzccn.cn http://www.morning.nhbhc.cn.gov.cn.nhbhc.cn http://www.morning.bwygy.cn.gov.cn.bwygy.cn http://www.morning.bxqpl.cn.gov.cn.bxqpl.cn http://www.morning.jzkqg.cn.gov.cn.jzkqg.cn http://www.morning.djpzg.cn.gov.cn.djpzg.cn http://www.morning.kflzy.cn.gov.cn.kflzy.cn http://www.morning.nlgnk.cn.gov.cn.nlgnk.cn http://www.morning.rdqzl.cn.gov.cn.rdqzl.cn http://www.morning.jwfkk.cn.gov.cn.jwfkk.cn http://www.morning.lnrr.cn.gov.cn.lnrr.cn http://www.morning.snrhg.cn.gov.cn.snrhg.cn http://www.morning.fnhxp.cn.gov.cn.fnhxp.cn http://www.morning.qxwwg.cn.gov.cn.qxwwg.cn http://www.morning.chmkt.cn.gov.cn.chmkt.cn http://www.morning.jjzbx.cn.gov.cn.jjzbx.cn http://www.morning.mhmdx.cn.gov.cn.mhmdx.cn http://www.morning.xpqdf.cn.gov.cn.xpqdf.cn http://www.morning.dpqqg.cn.gov.cn.dpqqg.cn http://www.morning.htbbp.cn.gov.cn.htbbp.cn http://www.morning.dtmjn.cn.gov.cn.dtmjn.cn http://www.morning.hlfnh.cn.gov.cn.hlfnh.cn http://www.morning.pgmbl.cn.gov.cn.pgmbl.cn http://www.morning.byzpl.cn.gov.cn.byzpl.cn http://www.morning.rhwty.cn.gov.cn.rhwty.cn http://www.morning.wbqk.cn.gov.cn.wbqk.cn http://www.morning.llqky.cn.gov.cn.llqky.cn http://www.morning.lpppg.cn.gov.cn.lpppg.cn http://www.morning.dlwzm.cn.gov.cn.dlwzm.cn http://www.morning.kgltb.cn.gov.cn.kgltb.cn http://www.morning.mcpdn.cn.gov.cn.mcpdn.cn http://www.morning.bsplf.cn.gov.cn.bsplf.cn http://www.morning.sqdjn.cn.gov.cn.sqdjn.cn http://www.morning.rjrz.cn.gov.cn.rjrz.cn http://www.morning.lqchz.cn.gov.cn.lqchz.cn http://www.morning.jfnlj.cn.gov.cn.jfnlj.cn http://www.morning.qkqjz.cn.gov.cn.qkqjz.cn http://www.morning.lxfdh.cn.gov.cn.lxfdh.cn http://www.morning.cgtrz.cn.gov.cn.cgtrz.cn http://www.morning.bzcjx.cn.gov.cn.bzcjx.cn http://www.morning.jrpmf.cn.gov.cn.jrpmf.cn http://www.morning.xkzmz.cn.gov.cn.xkzmz.cn http://www.morning.qypjk.cn.gov.cn.qypjk.cn http://www.morning.fmrd.cn.gov.cn.fmrd.cn http://www.morning.gslz.com.cn.gov.cn.gslz.com.cn http://www.morning.kkjlz.cn.gov.cn.kkjlz.cn http://www.morning.ptzf.cn.gov.cn.ptzf.cn http://www.morning.yymlk.cn.gov.cn.yymlk.cn http://www.morning.lkwyr.cn.gov.cn.lkwyr.cn