3
#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 类添加函数(向上转换对我来说是强制性的。我计划的程序要求它是这样的)。一旦创建了基类,我就不想碰它。这个问题是不是违反了一旦你创建了一个基类,你就不必修改它的原则了。有什么办法可以解决这个问题?ps:工厂设计模式和原型设计模式我都看过,但是好像都不能解决。

4

5 回答 5

4

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

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

于 2010-09-30T09:19:55.633 回答
3

好吧,我不确定您到底想要什么(以及为什么要这样),但是:

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_castwhich 将返回空指针。bb

于 2010-09-30T09:14:23.470 回答
2
int main()
{
        B *bb = new B;
        bb->bye();
        C *cc=new C;
        cc->sayonara();
}//main

这样就不再需要对基类进行修改了:)

于 2010-09-30T09:24:51.040 回答
1

动态转换是一个明智的选择。如果你对动态转换很感兴趣,你可以使用访问者设计模式:

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

仅在您真正需要时才这样做。

于 2010-09-30T09:27:59.647 回答
0

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

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

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

于 2010-09-30T09:44:30.730 回答