Closed hbsun2113 closed 5 years ago
带纯虚函数的类叫抽象类,这种类不能直接生成对象,而只有被继承,并重写其虚函数后,才能使用。抽象类和大家口头常说的虚基类还是有区别的,在 C# 中用 abstract 定义抽象类,而在 C++ 中有抽象类的概念,但是没有这个关键字。抽象类被继承后,子类可以继续是抽象类,也可以是普通类,而虚基类,是含有纯虚函数的类,它如果被继承,那么子类就必须实现虚基类里面的所有纯虚函数,其子类不能是抽象类。
我认为,虚基类:应该是“被virtual继承的类”,不是“含有纯虚函数的类”。
带纯虚函数的类叫抽象类,这种类不能直接生成对象,而只有被继承,并重写其虚函数后,才能使用。抽象类和大家口头常说的虚基类还是有区别的,在 C# 中用 abstract 定义抽象类,而在 C++ 中有抽象类的概念,但是没有这个关键字。抽象类被继承后,子类可以继续是抽象类,也可以是普通类,而虚基类,是含有纯虚函数的类,它如果被继承,那么子类就必须实现虚基类里面的所有纯虚函数,其子类不能是抽象类。
我认为,虚基类:应该是“被virtual继承的类”,不是“含有纯虚函数的类”。
被virtual继承的类,指的是虚继承吧? public A : virtual public B? 这是用来解决菱形继承问题的,与虚基类不是一个概念。
关于初始化列表问题,仓库中表述不当。
对于要初始化的对象,使用含参构造函数初始化也不够准确(含参构造函数也不一定是列表初始化),就是使用了初始化列表进行初始化,现改为:没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化
另外,仓库中 而是直接调用拷贝构造函数初始化
的原意是指下文的类B中含有类A的成员,对类B的列表初始化(就是你说的带参数构造函数)中要先调用类A的拷贝构造函数。抱歉当时写的时候没留意而对你照成困扰。
#include<iostream>
using std::cout;
using std::endl;
class A
{
public:
int i;
A() { cout << "A:默认构造函数" << endl; }
A(int& _i) : i(_i) { cout << "A:带参数构造函数" << endl; }
A(const A& _a) { cout << "A:拷贝构造函数" << endl; }
A& operator=(const A& _a) { cout << "A:赋值运算符" << endl; }
};
class B
{
public:
A a;
B() = delete;
B(A& _a) : a(_a) { cout << "B:带参数构造函数" << endl; }
B(const B& _b) = delete;
B& operator=(const B& _b) = delete;
};
int main()
{
cout << "a" << endl;
A a;
//B b0; // 编译出错,因为禁用了 B 的默认构造函数
//b0 = a; // 编译出错,因为禁用了 B 的赋值运算符
cout << "b1" << endl;
B b1 = a;
cout << "b2" << endl;
B b2(a);
return 0;
}
虚基类确实是虚继承中的基类,稍后改过来。大佬好眼力,感谢 @hbsun2113
看到您说
没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化
我认为:如果使用“初始化列表”对“没有默认构造函数的”的类成员进行初始化,应该也是调用了其“含参构造函数”吧?