我知道钻石继承被认为是不好的做法.但是,我有2个案例,我认为钻石继承可以很好地适应.我想问一下,您是否会建议我在这些情况下使用钻石继承,或者是否有其他设计可能更好.
案例1:我想在我的系统中创建代表不同类型"动作"的类.这些操作按以下几个参数进行分类:
我打算有以下设计:
// abstract classes
class Action
{
// methods relevant for all actions
};
class ActionRead : public virtual Action
{
// methods related to reading
};
class ActionWrite : public virtual Action
{
// methods related to writing
};
class ActionWithDelay : public virtual Action
{
// methods related to delay definition and handling
};
class ActionNoDelay : public virtual Action {/*...*/};
class ActionFlowA : public virtual Action {/*...*/};
class ActionFlowB : public …Run Code Online (Sandbox Code Playgroud) 剧透警报:也许是一个愚蠢的问题.:)
#include <iostream>
using namespace std;
class Base
{
public:
virtual void YourMethod(int) const = 0;
};
class Intermediate : private Base
{
public:
virtual void YourMethod(int i) const
{
cout << "Calling from Intermediate" << i << "\n";
}
};
class Derived : private Intermediate, public Base
{
public:
void YourMethod(int i) const
{
cout << "Calling from Derived : " << i << "\n";
}
};
int main()
{
}
Run Code Online (Sandbox Code Playgroud)
有人可以向我解释为什么会抛出编译器警告:
main.cpp:21: warning: direct …Run Code Online (Sandbox Code Playgroud) 我在C++标准中读到的关于注入类名的内容与我将要提供的示例程序的行为相矛盾(我认为).这是我读到的:
从3.4(第3段)
为了名称隐藏和查找的目的,类的注入类名(第9节)也被认为是该类的成员.
从9(第2段)
在看到类名后立即将类名插入到作用域中.类名也插入到类本身的范围内; 这被称为注入类名.出于访问检查的目的,inject-class-name被视为公共成员名称.
从这些我了解到,以下是一个结构良好的翻译单元,它成功编译.
#include <vector>
class X: std::vector<int>
{
vector mem;
};
Run Code Online (Sandbox Code Playgroud)
但是,我认为以下应该产生错误,但事实并非如此
#include <vector>
class X: std::vector<int>, std::vector<char>
{
vector mem; //compiles OK... mem is apparently std::vector<int>
};
Run Code Online (Sandbox Code Playgroud)
由于名称vector被注入到两个std::vector<int>并std::vector<char>作为仿佛公共成员名称,那么就应该通过X继承,因此,名称vector中X应该是明确的.我错过了什么吗?
PS我正在使用MSVC9.0
多重继承的构造函数是多次调用的吗?并且构造函数的调用顺序是什么?这取决于继承列表中的顺序吗?
这是一个例子(它只是为了使情况清晰,没有现实生活中的例子).
class Base {};
class DerivedBaseOne : public Base {};
class DerivedBaseTwo : public Base {};
class Derived : public DerivedBaseTwo, public DerivedBaseOne
{};
//somewhere in the code, is Base() called two times here?
Derived * foo = new Derived();
Run Code Online (Sandbox Code Playgroud)
Base()构造函数是否被调用两次?并且构造函数的调用顺序是什么?基地第一?或DerivedBaseOne()或DerivedBaseTwo()首先?
谢谢.
类文件可以实现多少个接口?类文件使用的接口数量是否有限制?提前致谢.
我试图创建两个类,第一个使用非const实现的函数,第二个使用const实现.这是一个小例子:
class Base {
protected:
int some;
};
class A : public virtual Base {
const int& get() const {
return some;
}
};
class B : public virtual Base {
int& get() {
return some;
}
};
class C : public A, B {};
C test;
test.get(); // ambiguous
Run Code Online (Sandbox Code Playgroud)
对get函数的调用是模糊的.无论const版本需要满足更多要求.(get对const的调用C也是模棱两可的,但是有一个可能的函数可以调用.)标准中有这种行为的原因吗?谢谢!
我得到了以下课程:
class ConstraintFailureSet(dict, Exception) :
"""
Container for constraint failures. It act as a constraint failure itself
but can contain other constraint failures that can be accessed with a dict syntax.
"""
def __init__(self, **failures) :
dict.__init__(self, failures)
Exception.__init__(self)
print isinstance(ConstraintFailureSet(), Exception)
True
raise ConstraintFailureSet()
TypeError: exceptions must be classes, instances, or strings (deprecated), not ConstraintFailureSet
Run Code Online (Sandbox Code Playgroud)
有没有搞错 ?
最糟糕的是我不能尝试super(),因为Exception是基于旧的类......
编辑:是的,我试图切换继承/ init的顺序.
编辑2:我在Ubuntu8.10上使用CPython 2.4.你刚才知道这种信息是有用的;-).无论如何,这个小谜语已经关闭了我同事的三个口.你将成为我当天最好的朋友......
class A
{
protected:
string word;
};
class B
{
protected:
string word;
};
class Derived: public A, public B
{
};
Run Code Online (Sandbox Code Playgroud)
如何word影响变量的可访问性Derived?我该如何解决?
当使用多重继承而不是使用组合或其他替代方案更容易解决问题时,您能提供一些真实示例吗?
什么时候应该使用多重继承?
为什么有些语言支持多重继承(C++,Python)而有些语言不支持(Java,Ruby)?我的意思是 - 基于什么因素,编程语言的创建者决定是否包括对MI的支持.
我试图理解书中有效的c ++语句.以下是多继承的继承图.


现在这本书说vptr需要每个类中的单独内存.它也做了以下声明
上图中的一个奇怪之处在于,即使涉及四个类,也只有三个vptrs.如果愿意,实现可以自由地生成四个vpt,但是三个就足够了(事实证明B和D可以共享一个vptr),并且大多数实现利用这个机会来减少编译器生成的开销.
我看不出有什么理由为什么每个类都要求为vptr提供单独的内存.我理解vptr是从基类继承的,可能是继承类型.如果我们假设它显示了带有继承的vptr的结果内存结构,那么它们如何才能生成该语句
B和D可以共享vptr
有人可以在多重继承中澄清一下vptr吗?
c++ ×7
inheritance ×4
oop ×2
architecture ×1
constructor ×1
interface ×1
java ×1
name-lookup ×1
overloading ×1
python ×1
vptr ×1
vtable ×1