目录
1,成员默认值
创建对象时,首先根据成员默认值进行赋值,然后再调用构造函数。
class A
{
int x = 3, y;
public:
void out()
{
cout << x << " " << y;
}
};
int main()
{
A a;
a.out();
return 0;
}
输出:3 -858993460
默认构造函数什么都不做,不会把未初始化的变量设为0
class A
{
int x = 3, y;
public:
A()
{
x=2, y = 4;
}
void out()
{
cout << x << " " << y;
}
};
int main()
{
A a;
a.out();
return 0;
}
输出:2 4
构造函数中重新对x进行了赋值。
2,default
#include <iostream>
using namespace std;
class MyClass
{
public:
int x=2,y=3;
MyClass()=default;
MyClass(int x,int y)
{
this->x=x,this->y=y;
}
void out()
{
cout<<x<<" "<<y<<endl;
}
};
int main() {
MyClass cs;
MyClass cs2(3,4);
cs.out();
cs2.out();
return 0;
}
default把构造函数设为默认构造函数,不需要函数体,即这个函数什么都不做。
3,delete
delete限定函数不可用
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass()=delete;
~MyClass()=delete;
static int* get()
{
static int x;
return &x;
}
};
int main() {
int *p = MyClass::get();
*p=123;
int *pp=MyClass::get();
cout<<*pp;
return 0;
}
默认构造函数设为delete之后,就不能调用默认构造函数了。
加了delete不代表这个函数不存在,只是不能用而已:
#include <iostream>
using namespace std;
class MyClass
{
public:
int x=5,y;
MyClass(int x)=delete;
};
int main() {
// MyClass cs;
return 0;
}
这里自定义构造函数加了delete之后,默认构造函数也没了
4,多继承
(1)多继承
#include <iostream>
using namespace std;
class X1
{
public:
int f()
{
return 1;
}
};
class X2
{
public:
virtual int f()
{
return 2;
}
};
class A:X1,X2
{
public:
int f()
{
return 3;
}
};
class B:public A
{
public:
int f() override
{
return 4;
}
};
int main() {
A a;
A* p = &a;
if(((X1*)p)->f()==a.f())cout<<"same ";
else cout<<"not same ";
if(((X2*)p)->f()==a.f())cout<<"same ";
else cout<<"not same ";
return 0;
}
输出:same, virtual function
多继承的子类,如果有和父类相同签名的函数,只要各父类有一个是虚函数,子类中就是虚函数。
如上代码中,X1和A中的f是覆盖hide,非多态,X2和A中的f是重写override,多态。
A中的f仍然可以用override修饰,这个时候它作为语法糖的作用就是,当且仅当若干个父类中至少有一个是虚函数的时候,编译通过。
(2)多继承的可见性
查了网上很多资料,基本都是一致的,多继承也区分共有继承、私有继承等。
不过我在本地clion实测,以及用力扣c++实测,结果显示就算写的是private继承结果也是共有继承。
(3)钻石问题
有多继承就会出现环,这就是钻石问题
其实最小的环是三角形,不过三角形纯属没必要,而钻石问题的场景,却是实实在在存在的,子类继承2个父类,2个父类都继承了祖父类
为了避免子类类实例化时两次调用祖父类的构造函数,析构时两次调用祖父类析构函数,可以把祖父类的构造函数和析构函数设为虚函数。
5,虚继承、虚基类
把祖父类的构造函数和析构函数设为虚函数,可以解决构造函数和析构函数在子类中有二重身的问题,
但对于普通成员,还是存在这个问题,解决方法是虚继承,让2个父类都虚继承祖父类,这个场景下的祖父类就叫虚基类。