Vio*_*ffe 27 c++ inheritance c++11 c++17
class B {
private:
friend class C;
B() = default;
};
class C : public B {};
class D : public B {};
int main() {
C {};
D {};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
I assumed that since only class C is a friend of B, and B's constructor is private, then only class C is valid and D is not allowed to instantiate B. But that's not how it works. Where am I wrong with my reasoning, and how to achieve this kind of control over which classes are allowed to subclass a certain base?
更新:正如其他人在评论中指出的那样,以上代码片段按我最初在C ++ 14而不是C ++ 17下的预期运行。将实例化更改为C c; D d;in main()确实可以在C ++ 17模式下正常工作。
Nat*_*ica 24
这是C ++ 17中新增的功能。C现在发生的事情被认为是合计的。由于它是一个聚合,因此不需要构造函数。如果我们查看[dcl.init.aggr] / 1,我们将得出一个聚合
集合是具有以下内容的数组或类
没有用户提供的,显式的或继承的构造函数([class.ctor]),
没有私有或受保护的非静态数据成员(条款[class.access]),
没有虚拟功能,并且
没有虚拟,私有或受保护的基类([class.mi])。
[?注:聚合初始化不允许访问受保护的基类和私有基类的成员或构造函数。?—尾注?]
我们会检查所有这些要点。您不必在声明的任何构造C或者D所以子弹1。你没有任何数据成员,所以第二颗子弹没有关系,所以第三子弹满足你的基类是公共的。
在C ++ 11/14和C ++ 17之间发生的更改使得聚合现在可以具有基类。您可以在此处看到旧的措辞,其中明确指出不允许使用基类。
我们可以通过检查性状证实了这一点 std::is_aggregate_v像
int main()
{
std::cout << std::is_aggregate_v<C>;
}
Run Code Online (Sandbox Code Playgroud)
将打印1。
请注意,由于C是B您的朋友可以使用
C c{};
C c1;
C c2 = C();
Run Code Online (Sandbox Code Playgroud)
作为初始化的有效方法C。由于D不是B唯一起作用的朋友,因此D d{};是聚合初始化。所有其他形式都尝试默认初始化,但由于D已删除默认构造函数,因此无法完成初始化。
| 归档时间: |
|
| 查看次数: |
1595 次 |
| 最近记录: |