如何使用派生类中的虚函数,该派生类在具有基类参数的另一个类中声明?

时间:2018-12-20 15:27:22

标签: c++ oop base derived

问题是我想从名为Resource的类中列出元素; 在另一个类中,我有一个用于此的函数:void KeyDistributionCenter::ListResources(),并且我想从派生类File或服务器类中调用一个称为PRINT的函数。类服务器和文件派生自资源。 我想这样做是因为在派生类中修改了PRINT函数。(在File中,例如,我打印输出文件,在Server中,只是普通的东西。)

在KeyDistributionCenter中,我有一个资源列表(而不是派生文件或服务器列表)。所以我怎么知道要调用哪个打印(什么派生类是从Resources那里来的),我该怎么做? 谢谢!

编辑:我从资源中获得的函数打印为虚空print();。而且我在想,如果我这样声明,它将知道可以访问File或Server中的print()函数。

编辑2:更精确地说:我在KeyDistributionCenter中有另一个函数RegisterResource(Resource&R),将Resources添加到std :: vector资源中(vector也来自KDC);假设我有一个资源文件,而我想要的只是当我从KeyDistributionCenter调用Print()函数时(知道我的资源矢量列表)以了解哪种资源,并从File或Server类中调用了print()函数。

2 个答案:

答案 0 :(得分:1)

多态的经典案例:

class Resource
{
public:
    virtual ~Resource() { }
    virtual void print() = 0;
};

class Server : public Resource
{
public:
    void print() override { std::cout << "server" << std::endl; }
};

class File : public Resource
{
public:
    void print() override { std::cout << "file" << std::endl; }
};

您只需要确保Resource类在其接口中提供了 virtual print函数(在上面的示例中,它是纯虚拟的,但这不是强制性的)。

现在可以。 G。有:

std::unique_ptr<Resource> r = new Server();
r->print();
r = new File();
r->print();

重要:您需要通过指针或引用来引用对象。如果不这样做,那么您将遇到一种称为“对象切片”的现象:

Resource r = Server(); // server part in r will be sliced away and a pure
                       // Resource object remains!!!

如果您有一些Resource类型的STL容器,也会发生这种情况:

std::vector<Resource> resources;

(但是,如果您的类是抽象的,即包含纯虚函数,那么您将根本无法做到这一点-确切地说:您可以创建向量,但不能将元素放入其中)。

编辑: 正如已经在注释中指出的那样,对象切片是实现中实际发生的事情。您需要重新设计。一个变体可能看起来像这样:

std::vector<std::unique_ptr<Resource>> resources;

void registerResource(std::unique_ptr<Resource> r)
{
    resources.emplace_back(std::move(r));
}

registerResource(std::make_unique<Server>());
registerResource(std::make_unique<File>());

此方案将资源的所有权转移到媒介,它可能满足您的需求。可能还有许多其他变体,但是无论您做什么,都需要在向量中使用指针(无论是否智能)或引用。

答案 1 :(得分:0)

您为所有资源调用相同的print()方法。这就是多态性的重点-以相同的方式处理相同类型的对象。代表您在幕后实现了一个虚拟表,该表知道实际调用哪个print()方法。下面的代码应该清楚:

#include <iostream>
#include <vector>
#include <memory>

using namespace std;

class Resource
{
public:
    explicit Resource() { }
    virtual ~Resource() { }

    virtual void Print() = 0;
};

class File : public Resource
{
public:
    explicit File() : Resource() { }
    virtual ~File() { }

    void Print() override { cout << "Print called from File class" << endl; }
};

class Server : public Resource
{
public:
    explicit Server() : Resource() { }
    virtual ~Server() { }

    void Print() override { cout << "Print called from Server class" << endl; }
};

class KeyDistributionCenter
{
public:
    explicit KeyDistributionCenter()
    {
        resources.emplace_back(make_unique<File>());
        resources.emplace_back(make_unique<Server>());
    }

    void ListResources()
    {
        for (const auto& resource : resources)
            resource->Print();
    }

private:

    vector<unique_ptr<Resource>> resources;
};

int main()
{
    unique_ptr<KeyDistributionCenter> hub = make_unique<KeyDistributionCenter>();
    hub->ListResources();
    getchar();
}