C 中的多态性.在基类上调用继承的方法
Polymorphism in C++. Calling inherited methods on base class
我正在尝试实现一个简单的文件系统。我有一个基类条目。我有两个从称为文件和目录的条目继承的类。目录包含条目对象列表。我有一种称为目录和文件的称为更改的方法,但没有输入。我希望我可以在输入对象上调用此方法,并且编译器会根据条目是目录还是文件来知道使用哪种方法。有什么方法可以做到这一点?
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 filen";
}
unordered_set<Entry*> s;
s.add(File);
s.add(Directory);
for each in s: each.changeDir(); //pseudo code
不幸的是,它告诉我尚未声明" changeir((方法"。我通常只为入口类制定一种方法,但它说目录在此范围内没有声明(显然,因为目录是派生的条目类(。我觉得我以前在Python中做过这种多态性。在C 中没有办法吗?谢谢。
编辑:集合将指针用于输入对象,而不是实际的输入对象。
edit2:看来虚拟类是解决此特定问题的解决方案。我相信,更好,更健壮的解决方案将是让每个目录包含一组文件和一组目录,而不是两者。
您需要虚拟方法:
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
对象,则切片将破坏您的所有艰苦工作:
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
指定符 - 这将确保您确实覆盖了基类方法,而不仅仅是声明新方法; - 您可能使用原始指针而不是
unique_ptr
,但这是高度建议的,因为您必须自己释放它们以避免记忆泄漏; - 尽管这有效,但建议在可能的情况下避免在接口中使用虚拟方法。例如,请参见此基本草药萨特(Sutter(的文章。
您可以使方法changedir
成为纯虚拟函数,然后您可以通过实例化基类对象的指针或参考来实现所需的行为(该指向文件或目录(然后调用该功能,通过多态性,它将被正确调用。[对象切片]
只要您仅参考指针或对目录的引用,就可以将其转发:
:class Directory;
class Entry {
...
virtual Directory* changeDir(Directory* dir, Directory* currentDir) = 0;
};
我认为,如果您想在整个集合上调用更改,则应确保所有元素都是目录的实例(因为这仅对它们有意义(,并声明设置为包含目录,而不是条目。
另一方面相关文章:
- C++意外调用继承类的函数
- 如何调用继承的重载运算符<<并在派生类的输出中添加更多文本?
- 从基类调用继承类的方法.C++
- 在 lambda 函数 g++-4.8 中调用继承的受保护子类型
- 如何在模板化类中调用继承类的函数
- C 中的多态性.在基类上调用继承的方法
- 使用某些"specialized"字段调用继承的方法
- C++调用继承的构造函数
- C++:从静态方法调用继承的静态方法
- 从父类调用继承的函数
- 在 C++ 中调用继承的类特定函数
- 未调用继承的重写方法
- C++:从全局函数调用继承的成员函数
- 从基类调用继承类的重载函数
- 调用继承的向量元素的成员函数
- 函数调用继承C++
- 从基类的静态模板方法中调用继承类的受保护 ctor 失败
- C++如何确保在使用虚拟继承时调用继承的函数而不是基函数
- 为什么我不能调用继承版本的 QWidget::isVisible()?
- 未调用/继承子类中的移动赋值运算符