简体   繁体   English

C ++从基类派生的类中调用函数,而无需强制转换且没有虚拟方法

[英]C++ Call a function in a derived class from base class without casting and no virtual methods

I was recently asked this question in an interview: 最近在一次采访中有人问我这个问题:

#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;
}

The conditions on the question were that the Base and Derived classes cannot be changed (for example changing the name of the methods, adding additional methods, or changing a method to virtual. A further restriction was that no type of cast could be used. The pointer p had to be used. Other than that, you could write any additional code, including as many classes as necessary to insure that the "bar()" method was called using the object pointed to by p. 问题的条件是不能更改基类和派生类(例如,更改方法的名称,添加其他方法或将方法更改为虚方法。另一个限制是不能使用强制类型转换。除此之外,您还可以编写任何其他代码,包括所需的尽可能多的类,以确保使用p指向的对象调用“ bar()”方法。

Given that no casts were allowed, the only aswer I could come up with was an old-school one: 考虑到不允许演员阵容,我唯一能想到的是老式的:

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

Which is even worse than a cast. 这比演员更糟糕。 The interviewer berated me and told me I didn't have even the most basic knowledge of object hierarchy since I could not see the very obvious, trivial solution to the question. 面试官指责我,并告诉我,我什至没有关于对象层次结构的最基本知识,因为我看不到该问题的非常明显且微不足道的解决方案。

I apologize if this question is a duplicate; 如果这个问题重复,我深表歉意。 I've seen other questions about accessing a method in a derived class from a base class, but in all cases I saw, the answer involved either a cast or modification to either of the classes. 我已经看到了有关从基类访问派生类中的方法的其他问题,但在所有情况下,答案都涉及对这两个类的转换或修改。

He may be correct; 他可能是正确的。 I've been programming in C++ for over 15 years and I cannot see the solution. 我从事C ++编程已有15年以上,看不到解决方案。 It could be I've never encountered it since I would use a cast in this situation: in this case, it would have to be a static_cast since there are no virtual methods (not even the destructor) which would allow the dynamic_vast to compile (it fails with a message: "'Base' is not a polymorphic type" 可能是我从未遇到过这种情况,因为在这种情况下我会使用强制类型转换:在这种情况下,它必须是static_cast,因为没有任何虚拟方法(甚至是析构函数)都无法使dynamic_vast进行编译(它失败并显示一条消息:“'Base'不是多态类型”

Simple and 简单和 easy 简单 dumb: 哑:

#define Base Derived

just before main . 就在main之前。 (you can then call bar on it) (然后您可以在其上调用bar

I maybe would come up with something like: 我也许会想出类似的东西:

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

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

And if the interviewer complains that this is too foobar, I would ask him to please ask less foobar questions :P 如果面试官抱怨这太愚蠢了,我想请他少问一些愚蠢的问题:P

No, really, I do consider this as a valid answer to a quite academic question. 不,真的,我确实认为这是一个相当学术性问题的有效答案。 I am using the object pointed by p (to call a foobar function) and I made sure that 'bar()' is called. 我正在使用p指向的对象(以调用foobar函数),并且确保已调用'bar()'。 I dont think such an exercise deserves a more sophisticated solution. 我认为这样的练习不值得一个更复杂的解决方案。 Logically, my solution cannot be distinguished from whatever solution the interviewer had in mind. 从逻辑上讲,我的解决方案无法与面试官所想到的任何解决方案区分开。

The pointer p had to be used. 必须使用指针p。 Other than that, you could write any additional code, including as many classes as necessary to insure that the "bar()" method was called using the object pointed to by p. 除此之外,您可以编写任何其他代码,包括所需的尽可能多的类,以确保使用p指向的对象调用“ bar()”方法。

As many classes as necessary, you say? 您说多少必要的课程?

#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();
}

答案可能是:无法编译。

You could use a union for type-punning: 您可以使用union进行类型修剪:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM