C++ 你有钻石继承有用的例子吗?

C++ 你有钻石继承有用的例子吗?,c++,C++,我对寻找钻石继承是件好事的例子很感兴趣。我只在理论上读过它,在实践中没有遇到过它。它有时会在基于接口的编程中出现,不过如果你小心的话,你可以避免它。这可能最好用一个例子来说明;否则,描述就会变成单词沙拉: // Foo.h struct IFoo { virtual ~IFoo() {} virtual int Bar() = 0; virtual int Baz() = 0; }; // FooBase.h #include "Foo.h" class FooBas

我对寻找钻石继承是件好事的例子很感兴趣。我只在理论上读过它,在实践中没有遇到过它。

它有时会在基于接口的编程中出现,不过如果你小心的话,你可以避免它。这可能最好用一个例子来说明;否则,描述就会变成单词沙拉:

// Foo.h

struct IFoo
{
   virtual ~IFoo() {}
   virtual int Bar() = 0;
   virtual int Baz() = 0;
};


// FooBase.h

#include "Foo.h"

class FooBase : public IFoo
{
public:
   int Bar() override { return 0; } // default implementation
   int Baz() override { return 0; } // default implementation
};


// ConcreteFoo.h

#include "Foo.h"

class ConcreteFoo : public IFoo
{
public:
   static ConcreteFoo* Create();
   virtual void SayHello() = 0;
};


// ConcreteFoo.cpp

#include "ConcreteFoo.h"
#include <iostream>

class ConcreteFooImpl : public ConcreteFoo, public FooBase
// Diamond! Both ConcreteFoo and FooBase descend from IFoo.
{
public:
   int Bar() override { return 1; }

   // use default Baz() from FooBase

   void SayHello() override { std::cout << "Hello!"; }
};

ConcreteFoo* ConcreteFoo::Create()
{
   return new ConcreteFooImpl();
}

在编写新代码时,通常可以首先避免创建这种安排。但是,如果您正在进行重构以打破遗留代码中的依赖关系,那么您有时会遇到类似于上面所述的情况,即中途停顿,或者可能是最后一站,这取决于它对您的困扰程度:。

它有时会在基于接口的编程中弹出,但如果您小心,可以避免出现。这可能最好用一个例子来说明;否则,描述就会变成单词沙拉:

// Foo.h

struct IFoo
{
   virtual ~IFoo() {}
   virtual int Bar() = 0;
   virtual int Baz() = 0;
};


// FooBase.h

#include "Foo.h"

class FooBase : public IFoo
{
public:
   int Bar() override { return 0; } // default implementation
   int Baz() override { return 0; } // default implementation
};


// ConcreteFoo.h

#include "Foo.h"

class ConcreteFoo : public IFoo
{
public:
   static ConcreteFoo* Create();
   virtual void SayHello() = 0;
};


// ConcreteFoo.cpp

#include "ConcreteFoo.h"
#include <iostream>

class ConcreteFooImpl : public ConcreteFoo, public FooBase
// Diamond! Both ConcreteFoo and FooBase descend from IFoo.
{
public:
   int Bar() override { return 1; }

   // use default Baz() from FooBase

   void SayHello() override { std::cout << "Hello!"; }
};

ConcreteFoo* ConcreteFoo::Create()
{
   return new ConcreteFooImpl();
}

在编写新代码时,通常可以首先避免创建这种安排。但是,如果您正在进行重构以打破遗留代码中的依赖关系,那么有时您会遇到类似于上面所述的情况,即中途停止,或者可能是最后一站,这取决于它对您的困扰程度:。

菱形继承的最佳示例是std::iostream库。这种设计需要彻底的测试。一般来说,我们应该尽可能避免这种类型的结构,以减少以后的维护问题。

菱形继承的最佳示例是std::iostream库。这种设计需要彻底的测试。一般来说,我们应该尽可能避免这种类型的结构,以减少以后的维护问题。

这是一件好事,虽然有点主观,但实际上在实际中使用的结构比您预期的更靠近家:。您可能在使用它时根本不知道它在那里。std::iostream库的菱形可能是基于接口编程的一个例子,有时,您的公共接口类从某个抽象基派生,而您的私有impl类则从该公共类和同一抽象基的某个具体实现派生。另一个示例可能是管道:Producer->Consumer/Producer->…->消费主义是一件有点主观的好事,但实际上是在离家较近的地方使用的。您可能在使用它时根本不知道它在那里。std::iostream库的菱形可能是基于接口编程的一个例子,有时,您的公共接口类从某个抽象基派生,而您的私有impl类则从该公共类和同一抽象基的某个具体实现派生。另一个示例可能是管道:Producer->Consumer/Producer->…->消费者