在c++ 11中可以在类之外执行继承吗?

Can I Perform inheritance outside of the class in C++11?

本文关键字:执行 继承 c++      更新时间:2023-10-16

假设我想在类之外用不同的指针类型重载一个函数。我能在c++ 11中做到这一点吗?

struct Bird;
struct Bear;
struct Animal {
    virtual Bird* AsBird() = 0;
    virtual Bear* AsBear() = 0;
};
struct Bird : public Animal{
    virtual Bird* AsBird(){ return this; }
    virtual Bear* AsBear(){ return NULL; }
};
struct Bear : public Animal{
    virtual Bird* AsBird(){ return NULL; }
    virtual Bear* AsBear(){ return this; }
};
void Print(Animal* a){
    cout << "I don't know what animal this is!" << endl;
}
void Print(Bear* b){
    cout << "That's a bear!" << endl;
}
void Print(Bird* b){
    cout << "That's a bird!" << endl;
}
int main(int argc, char* argv[]){
    Animal* a = new Bear;
    Bear* bear;
    Bird* bird;
    if (bear = a->AsBear()){
        Print(bear);
    } else if (bird = a->AsBird()){
        Print(bird);
    }
    return 0;
}

这段代码可以工作,但它绝对是可怕的。我尝试过使用模板和auto,但是编译器不希望与我的邪恶实验有任何关系。有合法的方式来做这件事吗?

您所做的是通过改变参数的类型来重载 Print free函数,没有涉及继承,这是完全合法的。

但是你不需要它(或任何dynamic_cast-like你所做的):你应该做的是在你的Animal基类中添加一个virtual void Print() const = 0,而不是在每个派生类中重写它。

例子:

struct Animal {
    virtual void Print() const = 0;
};
struct Bird : public Animal{
    void Print() const { cout << "That's a bird!n"; }
};
struct Bear : public Animal{
    void Print() const { cout << "That's a bear!n"; }
};
int main(){
    Animal* a = new Bear;
    a->Print();
    Animal* b = new Bird;
    b->Print();
}

正如quantdev所指出的,传统的方法是在你的类层次结构中添加一个虚拟函数。

但是,如果您不想这样做,您可以使用dynamic_cast,它是专门为这样的目的而发明的。

struct Animal {
    virtual ~Animal() {} // base class must have a virtual method to use dynamic_cast
};
...
if (bear = dynamic_cast<Bear*>(a)){
    Print(bear);
} else if (bird = dynamic_cast<Bird*>(a)){
    Print(bird);
}

这比你现有的要好一点:如果你添加另一个继承类,你不必改变你的基类;你只需要改变你的main函数并添加一个新的打印函数。

如果这仍然是"可怕的",也许你应该把Print作为一个虚函数。

这看起来像是访问者模式的一个用例。

struct Bird;
struct Bear;
struct Visitor
{
    virtual void Visit(Bird& x) = 0;
    virtual void Visit(Bear& x) = 0;
};
struct PrintVisitor : Visitor
{
    void Visit(Bird& x) override { cout << "That's a bird!" << endl; };
    void Visit(Bear& x) override { cout << "That's a bear!" << endl; };
};
struct Animal
{
    virtual void Accept(Visitor& v) = 0;
};
struct Bird : public Animal
{
    void Accept(Visitor& v) override { v.Visit(*this); }
};
struct Bear : public Animal
{
    void Accept(Visitor& v) override { v.Visit(*this); }
};
int main(int argc, char* argv[])
{
    Bear bear;
    Bird bird;
    PrintVisitor visitor;      
    Animal* a = &bear;
    a->Accept(visitor);
    a = &bird;
    a->Accept(visitor);
}

当然,使Print成为一个虚成员函数可能更容易。

AsBear, AsBird函数,您只是重新实现了dynamic_cast

对于Print的过载,这里最简单的解决方案是使Print成为Animal层次结构中的virtual函数。

我推荐的解决方案是使用访问者模式。因为这似乎是你试图通过解耦Print函数和类层次结构来做的。

#include <iostream>
struct Bird;
struct Bear;
struct Animal {
  struct Visitor {
    virtual void operator()(const Bird *) const = 0;
    virtual void operator()(const Bear *) const = 0;
  };
  virtual void Accept(const Visitor &visitor) const = 0;
};
struct Bird : public Animal {
  virtual void Accept(const Visitor &visitor) const override {
    visitor(this);
  }
};
struct Bear : public Animal {
  virtual void Accept(const Visitor &visitor) const override {
    visitor(this);
  }
};
struct Print : public Animal::Visitor {
  virtual void operator()(const Bird *) const override {
    std::cout << "Bird" << std::endl;
  }
  virtual void operator()(const Bear *) const override {
    std::cout << "Bear" << std::endl;
  }
};
int main() {
  Bird bird;
  Animal *animal = &bird;
  animal->Accept(Print());
}