#include<iostream>
using namespace std;

class Abs
{
        public:
        virtual void hi()=0;
};

class B:public Abs
{
        public:
        void hi() {cout<<"B Hi"<<endl;}
        void bye() {cout<<"B Bye"<<endl;}
};
class C:public Abs
{
        public:
        void hi() {cout<<"C Hi"<<endl;}
        void sayonara() {cout<<"C Sayonara"<<endl;}
};

int main()
{
        Abs *bb=new B;
        bb->bye();
        Abs *cc=new C;
        cc->sayonara();
}//main

编译器说

test2.cpp: In function ‘int main()’:
test2.cpp:26: error: ‘class Abs’ has no member named ‘bye’
test2.cpp:28: error: ‘class Abs’ has no member named ‘sayonara’

由于这个问题,每次创建继承自 Abs 类的新派生类时,我都必须向 Abs 类添加函数(向上转换对我来说是强制性的。我正在计划的程序要求如此)。一旦创建了基类,我就不想再触及它了。这个问题是否违反了一旦创建了基类,就不必修改它的原则。有办法解决这个问题吗?附:我看过工厂设计模式和原型设计模式,但这两个似乎都无法解决。

有帮助吗?

解决方案

好了,我不知道理解你想要什么(为什么你想这样),但:

int main()
{
        Abs *bb=new B;
        static_cast<B*>(bb)->bye();
        Abs *cc=new C;
        static_cast<C*>(cc)->sayonara();
}//main

将工作。

您只需要确保bb确实是一个B*static_cast之前。

您还可以使用dynamic_cast这将返回一个空指针如果bb是正确类型的未

其他提示

这违背了继承和抽象接口的目的。 byesayonara 两者都做同样的事情(说再见),只是用不同的语言。这意味着你应该有一个摘要 say_goodbye 被子类覆盖的方法。我想这是一个简化的示例,所以也许您可以描述您的实际场景,以便我们可以提供更具体的帮助。

编辑 如果您想通过抽象接口创建派生类的副本,请查看 这个问题. 。如果您想显式访问子类的不同属性,您应该问自己子类化在这里是否合适,因为您的类似乎没有太多共同点。

int main()
{
        B *bb = new B;
        bb->bye();
        C *cc=new C;
        cc->sayonara();
}//main

此在基类方式的修改都不再需要:)

动态铸造是明智的选择。如果你的宗教有关动态类型转换,你可以使用访问者设计模式:

struct Abs;
struct B;
struct C;

struct Visitor
{
    virtual ~Visitor() {}

    // Provide sensible default actions
    virtual void visit(Abs&) const { throw "not implemented"; }
    virtual void visit(B& b) const { visit(static_cast<Abs&>(b)); }
    virtual void visit(C& c) const { visit(static_cast<Abs&>(c)); }
};

struct Abs
{
    virtual ~Abs() {}
    virtual void hi() = 0;
    virtual void accept(Visitor const& v) { v.visit(*this); }
};

struct B : Abs
{
    void hi() { ... }
    void accept(Visitor const& v) { v.visit(*this); }
    void bye() { ... }
};

struct C : Abs
{
    void hi() { ... }
    void accept(Visitor const& v) { v.visit(*this); }
    void sayonara() { ... }
};

struct DoSayonara : Visitor
{
    void visit(C& c) const { c.sayonara(); }
};

struct DoBye : Visitor
{
    void visit(B& b) const { b.bye(); }
};

struct ByeOrSayonara : Visitor
{
    void visit(B& b) const { b.bye(); }
    void visit(C& c) const { c.sayonara(); }
};

和然后使用

Abs* b = new B(); Abs* c = new C();
b->accept(DoSayonara()); // Throw an exception
c->accept(DoSayonara()); // Do what is expected

做到这一点,只有当你真的需要它。

如果向上转换是强制性的,并且您需要调用子类中定义的方法,那么您就错了。

但是,在给定的时间点,您要么知道某个对象是特定的子类,在这种情况下您可以动态转换为该类型,要么不知道也不能确定是否可以调用该函数。

假设这与您有关 其他问题, ,我试图解释一种以不同方式实现该特定问题的方法 那里.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top