c ++继承抽象函数?

时间:2013-09-10 01:33:28

标签: c++ inheritance abstract

我有一个关于继承的基本问题,我似乎可以弄清楚,我已经完成了搜索而没有找到我想要的东西,所以我想我会在这里问(不知道我的标题是什么'我正在寻找是正确的。)

为了简单起见,我已经做了一些示例代码来说明我没有得到的东西。

基本上,如果我有一个父class A和两个子课B& C, 其中A包含常见内容(例如带有get / set的id), 而B& C具有特定于类的函数。 如果你声明一个类B,如:A *bObject = new B(); how do you then access the class specific function bObj-> specific()`?

我已尝试virtual,但这需要B和{ C声明了相同的函数名/原型。 我也尝试在A中声明摘要,但这要求原型位于A

我在哪里错了?对此有任何帮助,可能是基本问题会有所帮助。

#include <iostream>
using namespace std;
// A class dec
class A
{
public:
    A(void);
    ~A(void);
    char id;
    void setId(char id);
    char getId();
};

// B class dec - child of A
class B :
    public A
{
public:
    B(void);
    ~B(void);
    void sayHello();
};

//C class dec - child of A
class C :
    public A
{
public:
    C(void);
    ~C(void);
    void sayGoodby();
};

//a stuff
A::A(void)
{
}
A::~A(void)
{
}
void A::setId(char id)
{
    this->id = id;
}
char A::getId()
{
    return this->id;
}

//b stuff
B::B(void)
{
    this->setId('b');
}
B::~B(void)
{
}

// c stuff
C::C(void)
{
    this->setId('c');
}
C::~C(void)
{
}
void C::sayGoodby()
{
    std::cout << "Im Only In C" << std::endl;
}
// main
void main ()
{
    A *bobj = new B();
    A* cobj = new C();

    std::cout << "im class: " << bobj->getId() << endl;
    bobj->sayHello(); // A has no member sayHello
    std::cout << "im class: " << cobj->getId() << endl;
    cobj->sayGoodby(); // A has no member sayGoodby
    system("PAUSE");
}

感谢您的时间!

5 个答案:

答案 0 :(得分:0)

A *bobj = new B();
A* cobj = new C();

这里B和C的实例由A的指针指向。由于A没有B和C的成员函数sayHello()和sayGoodbye()的虚函数,它们不能被bobj->sayHello()和{{1调用}}。这不是多态性应该做的。

A类应该是:

cobj->sayGoodbye()

然后可以在不抱怨的情况下调用class A { public: A(void); ~A(void); char id; void setId(char id); char getId(); virtual void sayHello(){/* to do */ }; virtual void sayGoodbye(){ /* to do */ }; }; bobj->sayHello();

答案 1 :(得分:0)

A *bobj = new B();

bobj的静态类型为A *。因此,在编译时,编译器会在类A定义中查找成员函数,这是您尝试通过bobj访问的内容。现在,

bobj->sayHello();

由于sayHello的类型为A,编译器将在类bobj中查找A *。编译器不关心查看类B定义来解析调用。由于编译器在sayHello中找不到A成员,因此抱怨。

但是,动态类型bobjB *,这是根据动态类型调度调用的位置。

要解决此问题,您需要在virtual课程中使用A相同的功能。

答案 2 :(得分:0)

要访问派生类特有的方法,首先需要将基类指针强制转换为正确的派生类类型(向下转换):

A *bobj = new B();
bobj->sayHello(); // compile error
dynamic_cast<B*>(bobj)->sayHello(); // works
dynamic_cast<C*>(bobj)->sayGoodbye(); // run-time error - probably crashes with a segfault/access violation.

dynamic_cast确保运行时类型的安全性,但会给演员添加一些小开销;对于指针强制转换,如果指向对象实际上不是B,则返回空指针,并且在使用之前应检查返回值。或者,如果您确定要转换的指针指向正确的对象,则可以使用static_cast来节省运行时检查的成本,但如果指针未指向右侧对象,你会得到未定义的行为。

答案 3 :(得分:0)

您可以通过dynamic_cast<>使用向下投射。您可以在基类A中实现模板方法,以便于向下转换:

class A
{
public:
    A(void);
    virtual ~A(void);
    char id;
    void setId(char id);
    char getId();

    template <typename CHILD, typename R, typename... ARGS>
    R invoke (R (CHILD::*m)(ARGS...), ARGS... args) {
        CHILD *child = dynamic_cast<CHILD *>(this);
        if (child) return (child->*m)(args...);
        std::cout << "down cast error: " << typeid(CHILD).name() << std::endl;
    }
};

如果A的特定实例不是CHILD的基础,那么dynamic_cast<CHILD *>(this)会产生NULL。请注意,A中的dynamic_cast<>中的虚拟析构函数是必需的。

所以,你可以像这样使用它:

std::unique_ptr<A> bobj(new B());
std::unique_ptr<A> cobj(new C());

bobj->invoke(&B::sayHello);
bobj->invoke(&C::sayGoodbye);
cobj->invoke(&B::sayHello);
cobj->invoke(&C::sayGoodbye);

只有第一次和最后一次调用有效。中间两个将导致打印"down cast error"消息。

答案 4 :(得分:0)

如果你真的想调用这样的函数,你可以这样做:

A* bobj = new B();
((B*)bobj)->sayHello();//this can be dangerous if bobj is not an instance of class B

但是,这里的问题是你错误地进行了设计。 基本上,如果你创建一个类A,并将其子类化为B和C. 然后分配A * bobj = new B();你正在拆分接口和实现。这意味着您将使用bobj,就好像它是A类的实例一样。并且您不会在B或C中调用函数.B&amp; C是接口类A的实现。

就像你雇人建房一样。你给他们你的蓝图(接口)并雇用他们来构建。你可以随意改变蓝图,他们会在蓝图中做任何事情。但你不能直接订购它们(就像你不能直接从bobj调用sayHello())。