如何使用派生的 class 中的虚函数,在另一个 class 中使用基本 class 参数声明?
How to use a virtual function from derived class, declared in another class with base class parameters?
问题是我想列出来自 class 命名资源的元素;
在另一个 class 中,我有一个函数:void KeyDistributionCenter::ListResources()
我想从派生的 class 文件或 class 服务器调用一个名为 PRINT 的函数。 Class 服务器和文件派生自资源。
我想这样做是因为在我的派生 class 中我修改了 PRINT 函数。(例如,在文件中我打印输出文件,在服务器中只是一般的东西)。
在 KeyDistributionCenter 中,我有一个资源列表(不是派生文件或服务器的列表)。那么我怎么知道要调用哪个打印(派生 class 来自资源),我该怎么做呢?
谢谢!
编辑:我从资源中打印的函数是 virtual void print();我在想,如果我这样声明,它将知道从文件或服务器访问 print() 函数。
编辑 2:更准确地说:我的 KeyDistributionCenter 中有另一个函数 RegisterResource(Resource &R),它将资源添加到我的 std::vector 资源中(矢量也来自 KDC);假设我有一个资源文件,我想要的只是当我从 KeyDistributionCenter(我的资源向量列表)调用 Print() 函数时,以了解资源的类型并从文件或服务器调用 print() 函数 class
多态性的经典案例:
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
class 在其接口中提供了一个 virtual print
函数(在上面的例子中,它是纯虚拟,但这不是强制性的)。
现在你可以e。 G。有:
std::unique_ptr<Resource> r = new Server();
r->print();
r = new File();
r->print();
重要提示:您需要通过指针或引用来引用您的对象。如果你不这样做,那么你会遇到一种叫做 'object slicing':
的现象
Resource r = Server(); // server part in r will be sliced away and a pure
// Resource object remains!!!
这也会发生,如果你有一些 Resource
类型的 STL 容器:
std::vector<Resource> resources;
(你根本无法这样做,但是,如果你的 class 是抽象的,即包含纯虚函数——准确地说:你可以创建向量,但不能放置元素成).
编辑: 正如评论中已经指出的那样,对象切片是您的实现中实际发生的事情。你需要重新设计。一种变体可能如下所示:
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>());
此场景将资源的所有权转移给向量,它可能满足您的需求,也可能不满足您的需求。还有许多其他可能的变体,但无论你做什么,你都需要指针(智能或不智能)或向量中的引用。
您为所有资源调用相同的 print() 方法。这就是多态性的要点——以相同的方式处理相同类型的对象。虚拟 table 代表您在幕后实现,它知道实际调用哪个 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();
}
问题是我想列出来自 class 命名资源的元素;
在另一个 class 中,我有一个函数:void KeyDistributionCenter::ListResources()
我想从派生的 class 文件或 class 服务器调用一个名为 PRINT 的函数。 Class 服务器和文件派生自资源。
我想这样做是因为在我的派生 class 中我修改了 PRINT 函数。(例如,在文件中我打印输出文件,在服务器中只是一般的东西)。
在 KeyDistributionCenter 中,我有一个资源列表(不是派生文件或服务器的列表)。那么我怎么知道要调用哪个打印(派生 class 来自资源),我该怎么做呢? 谢谢!
编辑:我从资源中打印的函数是 virtual void print();我在想,如果我这样声明,它将知道从文件或服务器访问 print() 函数。
编辑 2:更准确地说:我的 KeyDistributionCenter 中有另一个函数 RegisterResource(Resource &R),它将资源添加到我的 std::vector 资源中(矢量也来自 KDC);假设我有一个资源文件,我想要的只是当我从 KeyDistributionCenter(我的资源向量列表)调用 Print() 函数时,以了解资源的类型并从文件或服务器调用 print() 函数 class
多态性的经典案例:
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
class 在其接口中提供了一个 virtual print
函数(在上面的例子中,它是纯虚拟,但这不是强制性的)。
现在你可以e。 G。有:
std::unique_ptr<Resource> r = new Server();
r->print();
r = new File();
r->print();
重要提示:您需要通过指针或引用来引用您的对象。如果你不这样做,那么你会遇到一种叫做 'object slicing':
的现象Resource r = Server(); // server part in r will be sliced away and a pure
// Resource object remains!!!
这也会发生,如果你有一些 Resource
类型的 STL 容器:
std::vector<Resource> resources;
(你根本无法这样做,但是,如果你的 class 是抽象的,即包含纯虚函数——准确地说:你可以创建向量,但不能放置元素成).
编辑: 正如评论中已经指出的那样,对象切片是您的实现中实际发生的事情。你需要重新设计。一种变体可能如下所示:
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>());
此场景将资源的所有权转移给向量,它可能满足您的需求,也可能不满足您的需求。还有许多其他可能的变体,但无论你做什么,你都需要指针(智能或不智能)或向量中的引用。
您为所有资源调用相同的 print() 方法。这就是多态性的要点——以相同的方式处理相同类型的对象。虚拟 table 代表您在幕后实现,它知道实际调用哪个 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();
}