首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对所有子类通用的抽象类方法

对所有子类通用的抽象类方法
EN

Stack Overflow用户
提问于 2022-08-03 17:31:46
回答 1查看 151关注 0票数 0

我正在设计一种采用继承的结构。父类是抽象的,基本上有两个方法。一个是纯粹的虚拟,另一个是,我不太确定我应该如何处理它。它只是一个用纯虚拟线程启动线程的函数,它对所有的子线程都是通用的,但我不知道这是否可能。

代码语言:javascript
复制
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:

代码语言:javascript
复制
th = std::thread([this](){this->do_watch();});

这似乎是编译,而不必给出类的名称。但我不知道这是否会导致一种不明确的行为。

EN

回答 1

Stack Overflow用户

发布于 2022-08-03 22:09:22

这里有一些东西可以帮助您重新意识到继承和纯虚拟函数的概念,以及其他人的利益(就像我一样,它被抛出用于继承的四重循环)。

通过使do_watch()成为一个纯粹的虚拟函数,您特别要对编译器说:“这个代码不是在这个结构/类中定义的,这个结构/类的每个子类都有它自己的定义。”

如果您需要一个函数来做一件事,并且只需要为每个孩子做一件事,那么您只需要在父级中定义它。您甚至不需要它成为一个虚拟函数,因为您不会在任何一个子函数中更改该方法。

以下面的结构为例。

代码语言:javascript
复制
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(),如果在子类中未定义虚拟函数,则在父类中定义的虚拟函数将被调用,否则将调用子函数的函数定义。例如:

代码语言:javascript
复制
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;
}

输出

代码语言:javascript
复制
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.不要把我们的话当作福音,我们只讲我们经历过的事情。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73225518

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档