我正在尝试实现一个简单的文件系统。我有一个基类条目。我有两个类继承自名为File和Directory的条目。目录包含Entry对象列表。我有一个名为changeDir的方法,用于目录和文件,但不是条目。我希望我可以在Entry对象上调用此方法,编译器将根据Entry是目录还是文件知道使用哪种方法。有什么方法可以实现这个目标吗?
class Entry{
public:
std::chrono::time_point<std::chrono::system_clock> dateCreated;
std::string fileName;
Entry(std::string name);
~Entry();
};
Directory* Directory::changeDir(Directory* dir, Directory* currentDir){
currentDir = dir;
return currentDir;
}
void File::changeDir(Directory* dir, Directory* currentDir){
std::cout<<"You cannot change directories into a file\n";
}
unordered_set<Entry*> s;
s.add(File);
s.add(Directory);
for each in s: each.changeDir(); //pseudo code
不幸的是,它告诉我还没有为Entry类声明changeDir()方法。我通常只为Entry类创建一个方法,但它表示Directory未在此范围内声明(显然,因为Directory是Entry的派生类)。我觉得我以前在python中做过这种类型的多态。在C ++中没有办法吗?谢谢。
编辑:Set接受指向Entry对象的指针,而不是实际的Entry对象。
Edit2:虚拟类似乎是解决这个特定问题的方法。我相信更好更强大的解决方案是让每个目录包含一组文件和一组directorys,而不是一组两者。
答案 0 :(得分:4)
您需要virtual methods:
struct Entry
{
virtual void changeDir( )
{
std::cout << "Entry" << std::endl;
}
};
struct File : Entry
{
virtual void changeDir( ) override
{
std::cout << "File" << std::endl;
}
};
struct Directory : Entry
{
virtual void changeDir( ) override
{
std::cout << "Directory" << std::endl;
}
};
但是,如果您的收藏品是普通Entry
个对象,slicing会破坏您所有的辛勤工作:
int main()
{
std::vector< Entry > entries;
entries.push_back( File { } );
entries.push_back( Directory { } );
entries[ 0 ].changeDir( ); // > Entry
entries[ 1 ].changeDir( ); // > Entry
为了保存正确的对象,你必须动态分配它们并存储某种指针:
std::vector< std::unique_ptr< Entry > > entryPointers;
entryPointers.push_back( std::make_unique< File >( ) );
entryPointers.push_back( std::make_unique< Directory >( ) );
entryPointers[ 0 ]->changeDir( ); // > File
entryPointers[ 1 ]->changeDir( ); // > Directory
}
有些观点:
override
specifier - 这将确保您真正覆盖基类方法而不只是声明一个新方法; unique_ptr
,但强烈建议不要这样做,因为您必须自己释放它们以避免内存泄漏; 答案 1 :(得分:1)
您可以使方法changedir
成为纯虚函数,然后通过实例化基类对象的指针或引用(将指向文件或目录)然后您可以实现所需的行为调用函数,通过多态,它将被正确调用。 [对象切片]
答案 2 :(得分:1)
只要你只引用指针或对Directory的引用,你就可以直接声明它:
class Directory;
class Entry {
...
virtual Directory* changeDir(Directory* dir, Directory* currentDir) = 0;
};
答案 3 :(得分:1)
我认为如果你想在整个集合上调用changeDir,你应该确保所有元素都是Directory的实例(因为它只对它们有意义),并将集合声明为包含目录,而不是条目。
另一方面,如果您的集合可能包含两种类型的条目,则不应该首先尝试在它们上调用可能未定义的方法。