c ++指向基类的指针没有派生类成员函数,但指针是用derived创建的

时间:2017-02-27 18:15:58

标签: c++ pointers inheritance derived-class base-class

我创建的类是指向基类的指针的容器。我可以添加基类对象以及派生类对象。但是,当我尝试使用派生类对象中的函数时,我得到了编译错误“'Base'类没有名为'name'的成员”。 代码看起来像这样:

    #include <cstdio>
    #include <vector>

    using namespace std;

    enum Type{
        obj,
        obj1,
        obj2
    };

    class Base{
        public:
            void fun(){
                printf("I'm base\n");
            }
    };

    class Derived1 : public Base{
        public:
            void fun2(){
                printf("I'm derived1\n");
            }
    };

    class Derived2 : public Base{
        public:
            void fun3(){
                printf("I'm derived2\n");
            }
    };

    class myVector{
        private:
            vector<Base*> objects;
        public:
            void add(Type type){
                switch(type){
                    case obj:
                        objects.push_back(new Base);
                        break;
                    case obj1:
                        objects.push_back(new Derived1);
                        break;
                    case obj2:
                        objects.push_back(new Derived2);
                        break;
                }
            }

            Base* operator[](unsigned index){
                return objects[index];
            }
    };

    int main(){
        myVector vec;
        vec.add(obj);
        vec.add(obj1);
        vec.add(obj2);
        vec[0]->fun();     // ok
        vec[1]->fun1();    // error "Base" has not member named "fun1"
        vec[2]->fun2();    // error "Base" has not member named "fun2"
    }

应打印

我是基地 我是派生的1 我是派生的2

但是我的编辑错误就像在评论中的代码一样

3 个答案:

答案 0 :(得分:1)

你应该把它变成虚函数并在派生类中重写它

#include <cstdio>
#include <vector>

using namespace std;

enum Type{
    obj,
    obj1,
    obj2
};

class Base{
    public:
        virtual void fun(){
            printf("I'm base\n");
        }
};

class Derived1 : public Base{
    public:
        void fun(){
            printf("I'm derived1\n");
        }
};

class Derived2 : public Base{
    public:
        void fun(){
            printf("I'm derived2\n");
        }
};

class myVector{
    private:
        vector<Base*> objects;
    public:
        void add(Type type){
            switch(type){
                case obj:
                    objects.push_back(new Base);
                    break;
                case obj1:
                    objects.push_back(new Derived1);
                    break;
                case obj2:
                    objects.push_back(new Derived2);
                    break;
            }
        }

        Base* operator[](unsigned index){
            return objects[index];
        }
};

int main(){
    myVector vec;
    vec.add(obj);
    vec.add(obj1);
    vec.add(obj2);
    vec[0]->fun();     // ok
    vec[1]->fun();     // now it works
    vec[2]->fun();     // now it works
}

答案 1 :(得分:0)

C ++在编译时静态解析名称。你告诉它你有Base*。这些是您通过该指针允许在该对象上使用的名称。想要访问Derived中您必须投射的内容。

答案 2 :(得分:0)

如果您希望能够通过基类指针调用方法,则需要在基类中定义这些方法(可能是纯虚方法)。

如果您知道自己有子类对象,则可能需要static_cast(或者可能dynamic_cast并测试),并通过强制转换指针调用该方法。

如果不了解fun1()fun2()的语义,就无法知道哪种替代方案最适合您的情况。

这是一个做你想要的版本 - 请注意Base::fun被声明为virtual,子类实现会覆盖它。

#include <iostream>
#include <vector>

struct Base {
    virtual void fun() const {
        std::cout << "I'm base" << std::endl;
    }
    virtual ~Base() = default;
};

struct Derived1 : public Base{
    void fun() const override {
        std::cout <<  "I'm derived1" << std::endl;
    }
};

struct Derived2 : public Base{
    void fun() const override {
        std::cout << "I'm derived2" << std::endl;
    }
};

int main(){
    std::vector<Base*> vec{new Base(), new Derived1(), new Derived2()};
    vec[0]->fun();
    vec[1]->fun();
    vec[2]->fun();

    // cleanup
    for (auto e: vec)
        delete e;
}