[英]Making C++ Classes inherit from C Structs, Recommended?
我最近在做一些 Windows Api 编码(还在做)。 我试图找到将 WNDCLASSEX 包装到 C++ class 中的最佳方法,当我有这个疯狂的想法时,WNDCLASSEX 是一个结构,对吗? (即使它是用 c 编写的)和 C++ 结构被视为类,所以我为什么不将我的 WinCLass 声明为 WNDCLASSEX 的派生,所以我尝试了:
class WinClass : protected WNDCLASSEX
它奏效了。 然后我尝试将它与 SDL 结构一起使用,但那些也有效。 但是当我从它们派生类时,某些结构(尤其是 SDL 结构)要么不编译,要么导致无法解释的运行时错误:所以我的问题? 是否推荐使用这种 C struct ,是否真的被专业人士使用? 或者它只是一个蹩脚的黑客,我应该使用我的包装器还是应用程序? 或者这只会引入无法解释的错误?
只要你不开始添加虚拟成员,应该没问题。 如果确实添加了虚拟成员,则虚拟表指针可能会与结构的 memory 布局发生冲突。
这包括虚拟析构函数!
class 和 C++ 中的结构之间的唯一区别是访问说明符。
对于类,访问说明符默认为私有。
对于结构,访问说明符默认是公共的。
这意味着如果你有一个从其他类/结构派生的 class 它将默认为私有 inheritance &
如果您有一个派生自其他类/结构的结构,默认情况下它将是一个公共 inheritance 。
但一个问题是,由于结构的默认访问说明符是公共的,它们可能会暴露可能不应该暴露给派生类的成员。 从这个意义上说,整个封装具有一个全新的维度。 当然,如果您可以更改您打算用作 Base 的结构中的访问说明符,则可以避免该问题,但可能无法避免,因为这可能会影响从其他部分使用该结构的方式该程序。
编辑:
通过评论,我现在有一个公平的想法,您指的是什么错误,这些错误并不是因为您是从结构派生的,而是因为您误解了 Inheritance 和访问说明符的规则。
下面是一个演示示例程序:
#include<iostream>
using namespace std;
struct FirstStruct
{
private:
int a;
public:
int b;
FirstStruct():a(10),b(20),c(30)
{
}
protected:
int c;
};
class MyClass:protected FirstStruct
{
public:
int i;
MyClass():i(40),j(50),k(60)
{
}
void doSomething()
{
a = 100; //private in Base is not accessible in Derived
b = 100; //Accessible
c = 100; //Accessible
i = 100; //Accessible
b = 100; //Accessible
c = 100; //Accessible
}
private:
int j;
protected:
int k;
};
int main()
{
MyClass obj;
obj.i = 100; //Accessible
obj.j = 100; //Error Cannot be Accessed, j is private member
obj.k = 100; //Error Cannot be Accessed, k is protected member
obj.a = 100; //Error Cannot be Accessed, a is private member in Base Class
obj.b = 100; //Error Cannot be Accessed;
//b is protected member of MyClass, because of protected Inheritance
obj.c = 100; //Error Cannot be Accessed;
//same reason as b
obj.doSomething();
return 0;
}
您可以在 Ideone 上查看运行相同的内容。
即使您将 Base 的类型从struct FirstStruct
为class FirstStruct
,您也会注意到,您会得到相同的错误(仅此而已)。
建议您在此处查看此答案,以清除您对 Inheritance 和访问说明符规则的理解。
我对 Win API 没有太多经验,但我知道在 C++ 中,类和结构之间的唯一区别是默认可见性。 对于类,它是私有的,对于结构,它是公共的。 换句话说,可以将 class 作为结构的子类。
请记住,由于为任何基础 class 声明虚拟析构函数是一种很好的做法,因此您要继承的结构不会拥有它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.