C++ / 钻石继承 / 静态变量
我面临一些设计问题,我想写:
class A { ... };
class B : public A { static string type_; ... };
class C : public A { static string type_; ... };
class D : public B, public C { static string type_; ... };
我认为在类C的定义之前,我不会有任何问题..但是当我定义类D时会发生什么?由于 D 将继承自 B 和 C,因此 i 可能会有一些不明确的内容。我的最终目标是在每个类 B、C 和 D 中都有一个具有相同名称但不同值的静态变量。这可能吗?
预先非常感谢 塞德
I am facing some design problems, I would like to write:
class A { ... };
class B : public A { static string type_; ... };
class C : public A { static string type_; ... };
class D : public B, public C { static string type_; ... };
I think up to the definition of class C, i won't have any problems.. but what will happen when i define class D? Since D will inherit from both B and C, i will probably have something ambiguous. My ultimate goal would be to have in each classes B, C and D a static variable which would have the same name, but a different value. Is that possible?
Many thanks in advance
Sed
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你这里的代码非常好。类可以用任何它们想要的名称来定义成员,即使它们与父类中的成员名称相匹配。您遇到麻烦的唯一一次是使用这些名称之一会导致歧义。
在您的情况下,类
B
、C
和D
中拥有三个static
数据成员不会导致任何问题问题和每个类的type_
实例将与所有其他类不同。仅仅因为它们具有相同的名称并不意味着 C++ 将它们视为覆盖。只有虚拟
成员函数可以被重写。在每个类及其成员函数的上下文中,对
name_
的任何引用都将始终引用该类中的name_
,因为类隐藏了其任何基类的名称,并且所以编译器只会查找当前类。在全局范围内,您可以使用完全限定名称引用name_
字段,例如A::name_
、B::name_
等。更重要的是,您在这里使用的继承类型(无论是虚拟的还是非虚拟的)并不重要,因为这里的问题只是变量的命名。由于每个
static
数据成员只有一个副本,因此您的类D
最终是否继承A::name_
的两个副本并不重要任何担忧;它不能继承两个副本,因为只存在一个。The code you have here is perfectly fine. Classes are allowed to define members with whatever names they want, even if they match the name of a member in a parent class. The only time you'll run into trouble is if using one of those names would lead to an ambiguity.
In your case, having three
static
data members in the classesB
,C
, andD
will not cause any problems and each class's instance oftype_
will be distinct from all the others. Just because they have the same name doesn't mean that C++ treats them as overrides; onlyvirtual
member functions can be overridden.Within the context of each class and its member functions, any references to
name_
will always refer to thename_
from that class, since classes hide names from any of their base classes and so the compiler will only look in the current class. Globally, you can refer to thename_
fields with their fully-qualified names, likeA::name_
,B::name_
, etc.More importantly, the type of inheritance you use here, whether virtual or non-virtual, does not matter because all that's at issue here is the naming of the variables. Since there's only one copy of each
static
data member, whether your classD
ends up inheriting two copies ofA::name_
isn't of any concern; it can't inherit two copies since only one exists.那里没有任何含糊之处。您可以将这两个字段称为
B::type_
和C::type_
。There is nothing ambiguous at all there. You will be able to refer to both fields as
B::type_
andC::type_
.如果您在
D
的方法中写入type_
,它将解析为D
的type_
。如果您编写A::name_
或B::name_
,它将解析为相应实例的type_
。另一方面,似乎您可能试图将某种反射系统破解到 C++ 上,因为每个类中都有名为
type_
的静态字段。在某些罕见的情况下,这可能很有用,但这可能是一个坏主意。If you write
type_
in a method inD
, it will resolve toD
'stype_
. If you writeA::name_
orB::name_
, it will resolve to the respective instance'stype_
.On a different note, it seems as if you might be trying to hack some kind of reflection system onto C++, since you have static fields called
type_
in each class. That might be useful under some rare circumstances, but it's probably a bad idea.在菱形继承中,C++ 标准提供了一种解决方案来避免出现歧义。
您的类定义结构看起来像
现在,当您在类 B 中继承类 A 时,
对类 C 使用以下相同的内容
。那么 C 就只有一个 A 类的实例。
不需要为 D 类进行虚拟继承。它没有任何效果。
类D的大小可以与之前相同,但是来自类B和类的变量访问的任何地址。当您创建 D 的实例时,C 类将是相同的。
In diamond inheritance there is one solution provided by C++ standard to avoid something ambiguous.
Your structure of class definition looks likes like
Now when you inherit class A in class B use following
Same things for class C.
So when any class inherit from class B & C then it will have just one instance of class A.
No need to virtual inherit for class D. It has no effect.
Size of class D may be same as before but any address of variable access from class B & class C will be same when you create instance of D.