据我了解,使用virtual
会抑制基类的构造函数,因此能够避免实例化基类的多个对象。
如果两个派生类的构造函数都被抑制,那么如何实例化基类的一个实例(从中派生虚拟类)?
如果抑制了基类的构造函数,当我有一个必须从其中一个虚拟类继承的新类时,基类的构造函数也将在那里被抑制吗?
我在下面用示例解释了我的问题。
class student{
int rollNo;
public : student(int a): rollNo(a) { }
int getRollNo() {
return rollNo;
}
};
class midsem : virtual public student{
float midSemMarks;
public : midsem(int a, float b) : student(a), midSemMarks(b) { }
float getMidSemMarks() {
return midSemMarks;
}
};
class endsem : virtual public student{
float endSemMarks;
public : endsem(int a, float b):student(a),endSemMarks(b) { }
float getEndSemMarks () {
return endSemMarks;
}
};
class total : public midsem, public endsem{
float totalMarks;
public:total(int a, float b, float c) :student(a), midsem(a,b), endsem(a,c) { }
float getTotal() {
return midsem::getMidSemMarks() + endsem::getEndSemMarks();
}
在上面的示例中,创建total
的对象时,实例化了student
的单个对象。
但是如果使用virtual
限制了endsem
和midsem
中学生的构造函数,那么在创建student
的对象时如何创建total
的一个实例?
现在,当我想创建另一个从endsem
派生的类时,将创建新类的对象,调用student
类的构造函数,就像使用virtual
应该抑制它?
答案 0 :(得分:1)
据我了解,使用virtual抑制了 基类,因此能够避免 实例化基类。
虚拟适用于继承关系;它抑制了任何中间派生类对虚拟基类构造函数的调用,无论该基是否在ctor-init-list中显式命名(在这种情况下,这意味着您将在没有该规则的情况下调用该基的默认构造函数) )。
如果两个派生类的构造函数都被抑制,则如何 基类的一个实例(虚拟类从该实例开始) 是派生的?
虚拟基类是从派生程度最高的类(不是中间类)中初始化的,无论是否在该类ctor-init-list中明确提及。 >
像往常一样,不提及基类就意味着将调用默认构造函数。
这意味着这些成员,构造函数必须可以从大多数派生类作为非静态成员进行访问。
仅当通过有效的可访问转换可访问基类时,非静态成员才可在派生类中访问,因此:
1)虚拟基础的私有继承会使代码格式错误:
class PrivateBase {}; class Der : virtual PrivateBase {}; class Der2 : Der {};
(请记住,默认情况下,使用关键字class
的成员和碱基是私有的。)
明确声明的特殊成员(构造函数,析构函数,赋值)遵循通常的规则,并且它们的定义必须有效,就像它们是显式编写的一样;因此,为了使Der2
有效,默认构造函数的Der2();
定义和Der2::Der2 () {}
必须有效。
所以Der () {}
的实际含义是Der () : PrivateBase () {}
(有效),而Der2 () : PrivateBase(), Der() {}
的格式错误。
2)由于虚拟继承固有的多种访问路径,并且由于仅需要可访问的路径,因此虚拟私有继承几乎永远不会阻止从以下类派生类:
class PrivateBase {};
class Der : virtual PrivateBase {};
class Der2bis : Der, virtual PrivateBase {};
此Der2bis
变体与Der2
几乎类似,除了虚拟基础再次被继承,这几乎使语义差异几乎为零(某些数据结构的布局可能会更改),除了虚拟现在可以直接访问PrivateBase
的{{1}}基,而没有给定从类成员获得Der2bis
派生基转换的可访问性(仍然不能从其他代码访问此转换)。
3)这意味着只有当派生程度最高的类成为基础的朋友时,才能使用私有构造函数。这意味着某些类可以派生,但是没有有效的构造函数定义:
Der2bis -> PrivateBase
请注意,class TheFriend;
class AllPrivate {
AllPrivate ();
AllPrivate (AllPrivate&);
friend class TheFriend;
};
class TheFriend : virtual AllPrivate { };
只能通过成为其朋友来默认构造其基类子对象(通过命名其默认构造函数)。
但是即使重复私有基础使其可访问,进一步推导也会失败:
TheFriend
在这里,私有基础可以访问,但是其成员仍然不可访问,class MoreDerived : TheFriend, virtual AllPrivate {};
不是朋友,并且不能调用基础构造函数,因此无论是隐式还是显式定义的构造函数都不能很好地使用形成。