c++ 指向基 class 的指针尚未派生 class 成员函数,但指针是使用派生创建的

c++ pointers to base class has not got derived class member functions but pointer is created with derived

我制作了 class,它是指向基 class 的指针的容器。我可以添加基础 class 对象以及派生的 class 对象。但是,当我尝试使用派生的 class 对象的函数时,出现编译错误“'Base' class 没有名为 '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
我是 derived2

但是我遇到了编译错误,就像评论中的代码一样

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

如果你希望能够通过一个base-class指针调用方法,那么这些方法需要在baseclass中定义(也许作为纯虚方法)。

如果你知道你有一个子class对象,你可能想要static_cast(或者可能dynamic_cast并测试),并通过强制转换指针调用该方法。

如果不了解 fun1()fun2() 的语义,就不可能知道哪种选择最适合您的情况。

这是一个可以满足您需求的版本 - 请注意 Base::fun 已声明 virtual 并且 subclass 实现会覆盖它。

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

您只需将其设为虚函数并在派生函数中覆盖它即可 class

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