C++ 让OOP正确

C++ 让OOP正确,c++,C++,好的,这是我的问题。我有以下课程: class Job { bool isComplete() {} void setComplete() {} //other functions }; class SongJob: public Job { vector<Job> v; string getArtist() {} void setArtist() {} void addTrack() {} string getTrack() {}

好的,这是我的问题。我有以下课程:

class Job {
   bool isComplete() {}
   void setComplete() {}
   //other functions
};

class SongJob: public Job {
   vector<Job> v;
   string getArtist() {}
   void setArtist() {}
   void addTrack() {}
   string getTrack() {}
   // other functions
};
// This were already implemeted
这里我只想让它显示函数只使用派生对象方法。因此,如果我有另一个从Job派生的对象,我需要将参数更改为Job,但是编译器不知道这些函数,我不知道应该为每个人测试什么类型的对象,然后强制转换它,以便调用正确的函数

所以把所有函数放在基类中是可以的,因为这样我就没有问题了,但是我不知道这是不是正确的OOP,如果一个类处理歌曲,另一个处理视频,我认为好的OOP意味着有两个类

如果我没有说清楚,请说清楚,我会尽量解释清楚。

简而言之,我想使用多病态。

您的问题来自于对对象调用过程方法的事实。作业类上应该有一个方法进程,并在派生类中重写此方法。

使用纯虚拟函数:

class Job
{
virtual string getArtist() =0;
};

将类
SongJob
VideoJob
的所有共同点放在一个公共基类中是完全正确的。但是,如果要添加与艺术家无关的
Job
子类,则会出现问题

关于您发布的代码,有一些事情需要注意。首先,你的班级
工作
显然不是一个职业。这意味着,你可以有工作,只是工作。不是
SongJob
也不是
VideoJob
。如果要明确说明不能存在简单的
作业
,请将基类抽象化:

class Job {
    virtual bool isComplete() = 0;
    virtual void setComplete() = 0;
   //other functions
};
现在,您无法创建
作业的实例

Job job; // compiler-error
std::vector<Job> jobs; // compiler-error
作业作业;//编译错误 std::向量作业;//编译错误 请注意,这些函数现在是虚拟的,这意味着子类可以重写它们。
=0
和end意味着子类必须提供这些函数的实现(它们是)

其次,您的类
SongJob
有一个成员
std::vector
。这几乎肯定不是你想要的。如果您将
SongJob
添加到此向量,它将成为正常的
作业
。这种效应称为。为了防止它,您必须将其设置为
std::vector


这里有更多的话要说,但那将是远远不够的。我建议您在基类
Job
中获得一个好的。

您可以将这些方法添加为
虚拟方法
,以便从
Job
派生的类可以覆盖或不覆盖这些特定方法

在您的
SongJob
类中,您重写了方法,但在
VideoJob

在中,
void process()
传递指向基类
Job

void process(Job *s) 

它将调用相应的方法,这取决于对象的地址,它指向的是<代码> SopJooWorks/Cuth>对象。

< P> C++中,必须做两件事情才能获得多态性:
  • 通过对基类型的引用(
    &
    )或指针(
    *
    )访问多态函数
  • 在基类型中将多态函数定义为
    virtual
因此,将这些更改为:

class Job {
  bool isComplete() {}
  void setComplete() {}
};

void process(SongJob s)
{
  // ...
}
致:

如果无法在基类上定义
process
内部所需的所有功能(如果您想要的所有成员函数都不适用于所有派生类型),则需要将
process
转换为
作业
上的成员函数,并使其虚拟化:

class Job {
  public:
  virtual bool isComplete() { }
  virtual void setComplete() { }
  virtual void process() = 0;
};

// ...

int main(int argc, char* argv[])
{
    SongJob sj;
    Job& jobByRef = sj;
    Job* jobByPointer = new SongJob();

    // These call the derived implementation of process, on SongJob
    jobByRef.process();
    jobByPointer->process();

    delete jobByPointer;
    jobByPointer = new VideoJob();

    // This calls the derived implementation of process, on VideoJob
    jobByPointer->process();

    return 0;
}
当然,您将有两种不同的
process
实现。每个类类型一个

人们会告诉你各种各样的“is-a”vs“has-a”的东西,以及关于这个愚蠢的“多态性”的各种复杂的事情;他们是对的

但从实用的角度来看,这基本上就是多态性的要点:这样你就不必在调用函数之前检查每个类的类型了。您可以只调用基类型上的函数,最终将调用正确的派生实现


虚拟…someFunc(…)=0意味着函数定义的类型不能实例化,必须在派生类中实现。它被称为“”函数,它所定义的类变成了“”。

是的,这就是我所做的,但是我需要使用typeid,因为一个Derved对象有一个hasNewTrack(),而另一个派生对象有一个hasnewClip(),所以基类对象没有任何这些,所以我得到了errorJob。进程可以是纯虚拟的(没有实现)。然后SongJob.Process将调用hasNewTrack,但它不会调用hasNewClip和VideoJob。Process将调用hasNewClip,但它不会调用hasNewTrack。因此,如果SonjJob有一个容器来存储歌曲,VideoJob有一个容器来存储视频,我应该将这些容器也放在基类中吗?我认为派生类不会有任何数据:“我知道OOP细节,我的问题是我需要用C++和java来实现这一点,所以我需要用两种语言来思考:)但是你的解释很好。Thanks@vBx:否,您可以将这些容器添加到类中。它们是不同的,因为一家只存储视频,而另一家只存储歌曲。这不是一个共同点,而是一个区别,因此它不属于基类。好的,我创建了一个基函数add(),在SongJob中我添加到songs容器中,在VideoJob中我添加到videos容器中,我想这是right@vBx:只有在
SongJob
v
中有
VideoJob
实例时才可以。如果您对此不满意,您将不得不在
SongJob
VideoJob
上使用非多态的
Add
方法,并且您将永远无法从基本类型访问
Add
。但是您仍然可以创建一个只读的
GetAllV
m
class Job {
  public: // You forgot this...
  virtual bool isComplete() { }
  virtual void setComplete() { }
};

void process(Job& s)
{
  // ...
}
class Job {
  public:
  virtual bool isComplete() { }
  virtual void setComplete() { }
  virtual void process() = 0;
};

// ...

int main(int argc, char* argv[])
{
    SongJob sj;
    Job& jobByRef = sj;
    Job* jobByPointer = new SongJob();

    // These call the derived implementation of process, on SongJob
    jobByRef.process();
    jobByPointer->process();

    delete jobByPointer;
    jobByPointer = new VideoJob();

    // This calls the derived implementation of process, on VideoJob
    jobByPointer->process();

    return 0;
}