我正在设计一种采用继承的结构。父类是抽象的,基本上有两个方法。一个是纯粹的虚拟,另一个是,我不太确定我应该如何处理它。它只是一个用纯虚拟线程启动线程的函数,它对所有的子线程都是通用的,但我不知道这是否可能。
struct Parent{
std::thread th;
void watch(){
th = std::thread(&______::do_watch, this);
};
virtual void do_watch() = 0;
};
struct Child1 : Parent{
void do_watch();
};
struct Child2 : Parent{
void do_watch();
};
struct Child3 : Parent{
void do_watch();
};正如您所看到的,方法watch实际上在所有子级上都是相同的,但是父级不知道这些子级,所以类似Child::do_watch这样的东西是不可能的。我真的必须把这个函数变成虚拟函数,然后把它复制到所有的子类中吗?
或者有一种方法可以与所有的子类共享这个函数,而不必在子类中重写它们(因为它无论如何都要调用do_watch,它是纯虚拟的,并且保证存在)。
Edit_1:
th = std::thread([this](){this->do_watch();});这似乎是编译,而不必给出类的名称。但我不知道这是否会导致一种不明确的行为。
发布于 2022-08-03 22:09:22
这里有一些东西可以帮助您重新意识到继承和纯虚拟函数的概念,以及其他人的利益(就像我一样,它被抛出用于继承的四重循环)。
通过使do_watch()成为一个纯粹的虚拟函数,您特别要对编译器说:“这个代码不是在这个结构/类中定义的,这个结构/类的每个子类都有它自己的定义。”
如果您需要一个函数来做一件事,并且只需要为每个孩子做一件事,那么您只需要在父级中定义它。您甚至不需要它成为一个虚拟函数,因为您不会在任何一个子函数中更改该方法。
以下面的结构为例。
struct Teacher
{
int nStudent;
Teacher():nStudent(20){}
int GetStudentNumber(){return nStudent;}
virtual int IncrementStudent ( ){ nStudent++ ; return nStudent;};
virtual void RemoveStudent()=0;
virtual void AddStudent() {nStudent++;};
void ParentRemove(){RemoveStudent();};
};
struct WeirdTeacher :public Teacher
{
void AddStudent(){nStudent+=10;}
void RemoveStudent(){nStudent-=10;}
};
struct SuperWeirdTeacher :public Teacher
{
void AddStudent(){nStudent-=1;}
int IncrementStudent(){nStudent+=2;return nStudent;}
void RemoveStudent(){nStudent+=nStudent;}
};
struct PseudoTeacher:public Teacher
{
private:
int nKidnappedStudent;
public:
void RemoveStudent(){
nKidnappedStudent = nStudent;
nStudent-=nStudent;
};
int GetKidnappedStudent(){return nKidnappedStudent;};
/* The code won't compile if you remove this
and remind you that the parent is an Abstract since it has at least one
pure virtual function */
};每个子结构都需要定义RemoveStudent()
每个子结构在调用RemoveStudent()时都将实现自己的ParentRemove()定义,并且必须对其有定义,即使该子结构不使用ParentRemove().While IncrementStudent(),如果在子类中未定义虚拟函数,则在父类中定义的虚拟函数将被调用,否则将调用子函数的函数定义。例如:
int main()
{
SuperWeirdTeacher swt;
WeirdTeacher wt;
PseudoTeacher pt;
swt.AddStudent();//Calls Child Definition
wt.AddStudent();//Calls Child Definition
pt.AddStudent();//Calls Parent Definition
// Calls Parent Definition
std::cout<<"Weird Teacher Has ["<<wt.IncrementStudent()<<"] Students"<<std::endl;
// Calls Child Definition
std::cout<<"Super Weird Teacher Has ["<<swt.IncrementStudent()<<"] Students"<<std::endl;
// Calls Parent Definition
std::cout<<"Pseudo Teacher Has ["<<pt.GetStudentNumber()<<"] Students"<<std::endl<<std::endl;
swt.ParentRemove(); // Calls Child Definition of RemoveStudent()
wt.ParentRemove(); // Calls Child Definition of RemoveStudent()
pt.ParentRemove(); // Calls Child Definition of RemoveStudent()
std::cout<<"Weird Teacher Has ["<<wt.GetStudentNumber()<<"] Students"<<std::endl;
std::cout<<"Super Weird Teacher Has ["<<swt.GetStudentNumber()<<"] Students"<<std::endl;
std::cout<<"Pseudo Teacher Has ["<<pt.GetStudentNumber()<<"] Students"<<std::endl<<std::endl;
std::cout<<"Pseudo Teacher Has Kidnapped["<<pt.GetKidnappedStudent()<<"] Students"<<std::endl;
return 0;
}输出
Weird Teacher Has [31] Students
Super Weird Teacher Has [21] Students
Pseudo Teacher Has [21] Students
Weird Teacher Has [21] Students
Super Weird Teacher Has [42] Students
Pseudo Teacher Has [0] Students
Pseudo Teacher Has Kidnapped [21] Students纯虚拟函数的全部目的是告诉编译器,函数的定义不是在父函数上,而是在子函数上,并在调用函数时使用它。这就是为什么th = std::thread([this](){this->do_watch();});起作用的原因,因为当从一个子类调用watch()时,它会引用子级的do_watch()定义,即使父类不知道do_watch()将为子类做什么(引用PseudoTeacher)。
为了改变中间发布的结构的想法,请原谅我的“黑暗扭曲”,这个例子是要展示你通过继承而获得的疯狂,但不要疯狂:) P.P.不要把我们的话当作福音,我们只讲我们经历过的事情。
https://stackoverflow.com/questions/73225518
复制相似问题