C++中最接近定义类的超类的东西是什么?

ein*_*ica 31 c++ idiomatic subclassing superclass

假设我有班级

class A {
protected:
    int x,y;
    double z,w;

public:
    void foo();
    void bar();
    void baz();
};
Run Code Online (Sandbox Code Playgroud)

在我的代码和其他代码中定义和使用.现在,我想写一些可以很好地在A上运行的库,但它实际上更通用,并且能够操作:

class B {
protected:
    int y;
    double z;

public:
 void bar();
};
Run Code Online (Sandbox Code Playgroud)

我确实希望我的库是通用的,所以我定义了一个B类,这就是它的API.

我希望能够告诉编译器 - 不是在我不再控制的A的定义中,而是在其他地方,可能在B的定义中:

请注意,请尝试将其B视为超类A.因此,特别是,将它放在内存中,这样如果我重新解释A*为a B*,我的代码期望B*s会起作用.并请然后实际接受A*B*(和A&作为B&等等).

在C++中,我们可以通过另一种方式执行此操作,即如果B是我们无法控制的类,则可以执行"子类已知类"操作class A : public B { ... }; 我知道C++没有相反的机制 - "通过新的B类超类化已知的A类".我的问题是 - 这个机制最接近可实现的近似值是多少?

笔记:

  • 这都是严格的编译时间,而不是运行时.
  • 可以有没有任何的变化class A.我只能修改B知道两者A和的代码的定义和代码B.其他人仍然会使用课程A,如果我希望我的代码与他们的代码进行交互,我也会这样做.
  • 这应该优选地是"可扩展的"到多个超类.所以也许我也class C { protected: int x; double w; public: void baz(); }应该表现得像一个超类A.

Sir*_*Guy 28

您可以执行以下操作:

class C
{
  struct Interface
  {
    virtual void bar() = 0;
    virtual ~Interface(){}
  };

  template <class T>
  struct Interfacer : Interface
  {
    T t;
    Interfacer(T t):t(t){}
    void bar() { t.bar(); }
  };

  std::unique_ptr<Interface> interface;

  public:
    template <class T>
    C(const T & t): interface(new Interfacer<T>(t)){}
    void bar() { interface->bar(); }
};
Run Code Online (Sandbox Code Playgroud)

我们的想法是使用封面下的类型擦除(即类InterfaceInterfacer<T>类)来允许C您接受任何可以调用的bar内容,然后您的库将获取类型的对象C.

  • @einpoklum使用引用,您会遇到对象生命周期的困难.这取决于你喜欢的. (7认同)
  • 请注意,这种技术可以在没有完全动态分配的情况下完成,特别是如果您只想要一个没有生命周期扩展的现有对象的"视图"或引用. (3认同)

Bat*_*eba 15

我知道C++没有相反的机制 - "超类已知类"

哦,是的,它确实:

template <class Superclass>
class Class : public Superclass
{    
};
Run Code Online (Sandbox Code Playgroud)

然后你走吧 所有在编译时,不用说.


如果你有一个class A无法更改的东西,需要将它插入一个继承结构,那么就使用一些东西

template<class Superclass>
class Class : public A, public Superclass
{
};
Run Code Online (Sandbox Code Playgroud)

请注意,指针dynamic_cast将到达A*指针Superclass*,反之亦然.同上Class*指针.此时,您已接近Composition,TraitsConcepts.

  • OP提到他不能改变派生类的定义. (4认同)
  • 那么,[这里](/sf/ask/3103132931/)我对此有疑问 (2认同)

Cal*_*eth 5

普通模板执行此操作,编译器将在您错误地使用它们时通知您.

代替

void BConsumer1(std::vector<B*> bs)
{ std::for_each(bs.begin(), bs.end(), &B::bar); }

void BConsumer2(B& b)
{ b.bar(); }

class BSubclass : public B 
{
    double xplusz() const { return B::x + B::z; }
}
Run Code Online (Sandbox Code Playgroud)

你写

template<typename Blike>
void BConsumer1(std::vector<Blike*> bs)
{ std::for_each(bs.begin(), bs.end(), &Blike::bar); }

template<typename Blike>
void BConsumer2(Blike& b)
{ b.bar(); }

template<typename Blike>
class BSubclass : public Blike 
{
    double xplusz() const { return Blike::x + Blike::z; }
}
Run Code Online (Sandbox Code Playgroud)

你使用BConsumer1和BConsumer2就像

std::vector<A*> as = /* some As */
BConsumer1(as); // deduces to BConsumer1<A>
A a;
BConsumer2(a); // deduces to BConsumer2<A>

std::vector<B*> bs = /* some Bs */
BConsumer1(bs); // deduces to BConsumer1<B>
// etc
Run Code Online (Sandbox Code Playgroud)

并且,您将拥有BSubclass<A>BSubclass<B>使用B界面执行某些操作的类型.