C++11还支持委托构造函数。 委托构造函数允许构造函数调用同一个类的其他构造函数,该构造函数必须放在构造函数初始化器中。 例如:
#include
using namespace std;
class A
{
private:
int i=5;
string str=”初始值”;
public:
A(){
str=”委托构造函数”;
i=99;
}
A(int ii):A(){
//不能写成AA(int ii):A(),i(ii)
//委托构造函数不能再利用初始化器初始化其他数据成员
i=ii;
}
void show(){
cout<<”i=”<<i<<”,str=”<<str<<endl;
}
};
int main()
{
A a(10);
a.show();
}
运行结果:
但是要注意不要递归委托:例如
#include
using namespace std;
class A
{
private:
int i=5;
string str=”初始值”;
public:
A(string ss):A(555){
str=ss;
}
A(int ii):A(“OK”){
//不能写成AA(int ii):A(),i(ii)
//委托构造函数不能再利用初始化器初始化其他数据成员
i=ii;
}
void show(){
cout<<”i=”<<i<<”,str=”<<str<<endl;
}
};
int main()
{
A a(10);
a.show();
}
编译结果:
可以看出,编译并不会报错,但是运行的时候就出错了!
—————————————————————————————————————————————————— //写的错误或者不好的地方请多多指导,可以在下面留言或者给我发邮件,指出我的错误以及不足,以便我修改,更好的分享给大家,谢谢。 转载请注明出处:https://www.royalchen.com/ author:royalchen Email:royalchen@royalchen.com ———————————————————————————————————————————————————

但有一点要注意的就是,如果构造函数体内有数据成员是使用new来分配空间的话,如果不手动编写复制构造函数,就会出错!
看似似乎a,b,c的地址都不一样,一开始我也很疑惑。但是在gdb下面调试发现其实并不是这样。 而且运行的时候也提示了两次free了同一内存。看析构中的输出也可以分析出是在free中出现了问题。 用GDB调试查看:
可以看出,实际上str地址都是一样的。都是指向同一个内存单元0X603010,而&a.str的地址都不相同。难道是说&a.str是指存放这个变量地址的地址?似乎只有这样才能说的通。使用p a.str查看,果然如此。
C++11同样提供了显式默认或者删除复制构造函数。方法和默认构造函数一致。 显式默认复制构造函数。 A(const A &a)=default; 显式删除复制构造函数 A(const A &a)=delete; 这样,编译器就将禁止使用复制构造函数。编译结果: 
还有一种方法就是利用移动语义以及右值引用,这里由于我也不是和熟练,就先不写了。
可以看到,执行
这说明了 A c=a;调用的不是赋值运算符而是复制构造函数。如何区分呢? 一般来说,类似于声明的使用的是复制构造函数,类似于赋值的使用的是赋值运算符。 当然,C++11也允许显式默认和删除赋值运算符,规则和复制构造和默认构造一样。
但是需要注意的是,有时候编译器会进行自动转换。
可以看到,int自动转换为了char类型。 如果不希望自动转换,在C++11中支持删除指定重载函数的方法.
这样就可以阻止自动转换了. 需要注意的是:一些看起来参数不一样的函数时不能共存的。例如
编译器将自动调用最匹配的那一个函数。 这个就是普通的函数重载,在类外的情况。 其实这个可以通过模板函数来代替,并且更加高效。
这个跟类外的函数重载几乎没有区别,只是这一次需要对象来调用方法而已. GCC还有个奇怪的行为,
可能这个是为了留给用户更多选择的余地吧. 同时要记住是可以通过const重载的,即参数是const和非const也算是不同的参数. 在C++11里面,可以显式删除某个重载方法.例如:
可以看到char被转换为了int类型,这或许不是我们想要的. 因此我们可以手动删除这个重载方法.
这个就是类里面的函数重载了. 需要注意的是继承的时候继承类中的重载有比较大的区别.请看下一篇博文.
通过方法的重写,即可定义同一函数在继承层次中的不同行为! 如果在子类中使用父类虚方法的名称,但是参数不同,那么这个不是重写父类的方法,也不会重载方法,而是创建一个新方法.
这个时候,父类中的show()方法将被隐藏,即dirved类中无法再使用show(int,string)方法.
可以看出,对于dirved类来说,show(int,string)这个方法被隐藏起来了,即对于dirved对象来说不可见了!因此只要在子类中重新定义了父类的虚方法,父类中的所有与该方法重载的方法都将被隐藏! 这一点需要特别注意! 下面再看一些有趣的东西:
结果没有疑问.但是如果你重写子类的show方法的时候,发现应该用double代替int,于是i更改为
看到没有!最后那个ref.show(int,string)调用了base里面的show方法!(100可以换成9.8更明显) 明明是dirved对象的引用,怎么就调用了base里面的show方法呢?因为这实际上是创建了一个新方法! 可用override关键字来避免这种情况!
override表示你是想要重写base类的show方法而不是创建一个新的show方法,因此如果参数不对就会报错! 需要注意的是,即便是重写,只要在子类中重新定义了,父类中的相应重载函数都将会被隐藏! 如果不想既想使用父类中的show,又想重写某一个show(),可以利用using
这样就两全其美啦! —————————————————————————————————————————————————— //写的错误或者不好的地方请多多指导,可以在下面留言或者给我发邮件,指出我的错误以及不足,以便我修改,更好的分享给大家,谢谢。 转载请注明出处:
但是,再看下面的测试!
因此可以看到,当用一个基类的指针指向一个派生类的对象,直接删除该指针时,析构函数调用链将会遭到破坏.
因此应该记得将析构函数声明为virtual,这样就永远不用担心析构函数调用链遭到破坏!
可以看出,通过指针和引用可以调用对应的虚函数.即便指针和引用都声明为Animal 类型,但是却可以调用相应的函数(Dog::speak()). 因此,如果需要在派生类中重新定义基类的方法,应该将该方法设置为虚方法. 需要注意的是只有指针和引用才能正确引发相应的虚函数.同时函数必须声明为虚的.如果不是的话,将只会调用相应的类成员函数. 例如:
如果成员函数不是虚的,就不能达到这样的效果.这就是动态绑定. 再看一个例子:
—————————————————————————————————————————————————— //写的错误或者不好的地方请多多指导,可以在下面留言或者给我发邮件,指出我的错误以及不足,以便我修改,更好的分享给大家,谢谢。 转载请注明出处:
如果引用未被初始化,编译将报错。 修改引用: 引用总是指向初始化的那个变量,也就是说,引用一旦被创建并初始化之后就无法改变。这一规则有点让人迷惑。、 如果声明了一个引用的同时使用一个变量赋值了,那么这个引用就会一直指向这个变量。 在此后使用变量对引用赋值,被引用变量的值变为被赋值变量的值。而引用不会因此更新从而指向这个变量。 例子:
注意:对引用取地址的结果和对被引用的变量取地址的结果是相同的! 可以看出,改变的只是引用变量x的值,并没有改变引用的指向. 或许你试图想通过在给引用赋值的时候取y的地址,绕过这一限制,r1=&y; 但是这样编译会报错
r1的实质是一个int型的引用,而&y则是一个int的指针,两者不能转换。 无法创建未命名值(例如一个整型值11,实质上这就是一个右值)的引用,除非这是一个const值。
这句语句意味着可以改变11的值,而这样做是没有意义的。 但是如果是const的引用,则可以运行。
二:在fedora20/linux 64bit下测试 gcc version=4.8.2
可以看出,在Windows 32bit里面,指针是用4个字节来表示的,也就是4*8=32bit; 在linux 64bit里面,指针用8个字节表示,8*8=64,可以看出这里面的规律了吧。那么在16bit里面,是不是用16/8=2来表示的呢? 这个留给你们自己去测试吧。 —————————————————————————————————————————————————— //写的错误或者不好的地方请多多指导,可以在下面留言或者给我发邮件,指出我的错误以及不足,以便我修改,更好的分享给大家,谢谢。 转载请注明出处: