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”的东西,以及关于这个愚蠢的“多态性”的各种复杂的事情;他们是对的
但从实用的角度来看,这基本上就是多态性的要点:这样你就不必在调用函数之前检查每个类的类型了。您可以只调用基类型上的函数,最终将调用正确的派生实现
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;
}