C ++从基类调用派生类中的函数而不进行强制转换,也没有虚拟方法

时间:2015-02-20 15:28:31

标签: c++ inheritance

我最近在接受采访时被问到这个问题:

#include <iostream>
class Base
{
public:
    void foo() { std::cout << "foo" << std::endl; }
};

class Derived : public Base
{
public:
    void bar() { std::cout << "bar" << std::endl; }
};

int main(int argc, const char *argv[])
{
    Base *p = new Derived;
    // additional code here
    return 0;
}

问题的条件是无法更改Base和Derived类(例如,更改方法的名称,添加其他方法或将方法更改为virtual。 进一步的限制是不能使用任何类型的铸件。 必须使用指针p。 除此之外,您可以编写任何其他代码,包括必要的多个类,以确保使用p指向的对象调用“bar()”方法。

鉴于没有允许任何演员阵容,我能想到的唯一一个是老派的:

Derived *d;
memcpy(&d, &p, sizeof p);
d->bar();

哪个比演员更糟糕。 面试官骂我并告诉我,我甚至没有对象层次结构的最基本知识,因为我看不出这个问题的非常明显,微不足道的解决方案。

如果这个问题重复,我道歉;我已经看到了有关从基类访问派生类中的方法的其他问题,但在我看到的所有情况下,答案都涉及对任一类的强制转换或修改。

他可能是正确的;我用C ++编程超过15年,我看不到解决方案。可能是我从未遇到过它,因为在这种情况下我会使用强制转换:在这种情况下,它必须是static_cast,因为没有虚拟方法(甚至是析构函数)都不允许dynamic_vast编译(它失败并显示一条消息:“'Base'不是多态类型”

5 个答案:

答案 0 :(得分:6)

简单且容易哑:

#define Base Derived

main之前。 (然后你可以在上面调用bar

答案 1 :(得分:2)

我可能想出类似的东西:

void foobar(Base* b){
   Derived d;
   d.bar();    
}

int main(int argc, const char *argv[]){
    Base *p = new Derived;
    foobar(p);
    return 0;
}

如果面试官抱怨说这太过于foobar,我会请他请求更少的foobar问题:P

不,真的,我认为这是一个非常学术性问题的有效答案。我正在使用p指向的对象(调用foobar函数),我确保&#39; bar()&#39;叫做。我不认为这样的练习应该得到更复杂的解决方案。从逻辑上讲,我的解决方案无法与面试官想到的任何解决方案区分开来。

答案 2 :(得分:1)

  

必须使用指针p。除此之外,您可以编写任何其他代码,包括必要的多个类,以确保使用p指向的对象调用“bar()”方法。

你说的必要的课程数量很多吗?

#include <iostream>

class Base
{
public:
    void foo() { std::cout << "foo" << std::endl; }
};

class Derived : public Base
{
public:
    void bar() { std::cout << "bar" << std::endl; }
};

int main()
{
    class Base
    {
    public:
        void bar() { std::cout << "bar" << std::endl; }
    };
    class Derived : public Base
    {
    };
    Base *p = new Derived;
    p->bar();
}

答案 3 :(得分:0)

答案可能是:这不会编译。

答案 4 :(得分:0)

您可以使用union进行类型惩罚:

union {
    Base* bp;
    Derived* dp;
} my_union = {p};
my_union.dp->bar();