简体   繁体   English

当后代需要不同的参数列表时,应如何在基类中定义抽象方法?

[英]How should I define an abstract method in the base class when descendants need different parameter lists?

Here is my code: 这是我的代码:

class LibItem
{
public:
    virtual void PrintDetails() = 0;
    virtual void setDetails() = 0;
    void setTitle(string TitleName)
    {
        Title = TitleName;
    }
    string getTitle()
    {
        return Title;
    }
    void setReleaseDate(string date)
    {
        ReleaseDate = date;
    }
    string getReleaseDate()
    {
        return ReleaseDate;
    }
    void setAuthor(string AuthorName)
    {
        Author = AuthorName;
    }
    string getAuthor()
    {
        return Author;
    }
    void setCopyright(string CopyrightDetails)
    {
        Copyright = CopyrightDetails;
    }
    string getCopyright()
    {
        return Copyright;
    }
    void setGenre(string GenreDetails)
    {
        Genre = GenreDetails;
    }
    string getGenre()
    {
        return Genre;
    }
    void setStatus(string StatusDetails)
    {
        Status = StatusDetails;
    }
    string getStatus()
    {
        return Status;
    }
private:
    string Title;
    string ReleaseDate;
    string Author;
    string Copyright;
    string Genre;
    string Status;
};

class Book : public LibItem
{
public:
    Book(string TitleName)
    {
        setTitle(TitleName);
    }
    void setISBN(int ISBNDetails)
    {
        ISBN = ISBNDetails;
    }
    int getISBN()
    {
        return ISBN;
    }
    void setDetails(string setBookTitle, string setBookAuthor, string setBookReleaseDate, string setBookCopyright, string setBookGenre, string setBookStatus, int setBookISBN)
    {
        setTitle(setBookTitle);
        setAuthor(setBookAuthor);
        setReleaseDate(setBookReleaseDate);
        setCopyright(setBookCopyright);
        setGenre(setBookGenre);
        setStatus(setBookStatus);
        setISBN(setBookISBN);
    }
    void PrintDetails()
    {
        cout << "Title: " << getTitle() << endl;
        cout << "Author: " << getAuthor() << endl;
        cout << "Release Date: " << getReleaseDate() << endl;
        cout << "Copyrite: " << getCopyright() << endl;
        cout << "Genre: " << getGenre() << endl;
        cout << "Status: " << getStatus() << endl;
        cout << "ISBN: " << getISBN() << endl;
    }

private:
    Book();
    int ISBN;

};

class DVD : public LibItem
{
public:
    DVD(string TitleName)
    {
        setTitle(TitleName);
    }
    void setRunningTime(int RunningTimeDetails)
    {
        RunningTime = RunningTimeDetails;
    }
    int getRunningTime()
    {
        return RunningTime;
    }
    void setDirector(string DirectorDetails)
    {
        Director = DirectorDetails;
    }
    string getDirector()
    {
        return Director;
    }
    void setStudio(string StudioDetails)
    {
        Studio = StudioDetails;
    }
    string getStudio()
    {
        return Studio;
    }
    void setProducer(string ProducerDetails)
    {
        Producer = ProducerDetails;
    }
    string getProducer()
    {
        return Producer;
    }
    void setDetails(string setDVDTitle, string setDVDAuthor, string setDVDReleaseDate, string setDVDCopyright, string setDVDGenre, string setDVDStatus, int setDVDRunningTime, string setDVDDirector, string setDVDStudio, string setDVDProducer)
    {
        setTitle(setDVDTitle);
        setAuthor(setDVDAuthor);
        setReleaseDate(setDVDReleaseDate);
        setCopyright(setDVDCopyright);
        setGenre(setDVDGenre);
        setStatus(setDVDStatus);
        setDirector(setDVDDirector);
        setStudio(setDVDStudio);
        setProducer(setDVDProducer);
    }
    void PrintDetails()
    {
        cout << "Title: " << getTitle() << endl;
        cout << "Author: " << getAuthor() << endl;
        cout << "Release Date: " << getReleaseDate() << endl;
        cout << "Copyrite: " << getCopyright() << endl;
        cout << "Genre: " << getGenre() << endl;
        cout << "Status: " << getStatus() << endl;
        cout << "Running Time: " << getRunningTime() << endl;
        cout << "Director: " << getDirector() << endl;
        cout << "Studio: " << getStudio() << endl;
        cout << "Producer: " << getProducer() << endl;
    }

private:
    DVD();
    int RunningTime;
    string Director;
    string Studio;
    string Producer;

};

I am having trouble with the virtual void setDetails(); 我在使用虚拟void setDetails()时遇到麻烦;

I am wanting both the Book and DVD class to have a method called setDetails to set the details. 我希望Book和DVD类都具有一个名为setDetails的方法来设置详细信息。 The problem is, both the Book class and the DVD class have different arguments for this method. 问题在于,Book类和DVD类都为此方法使用了不同的参数。

How can I achieve this? 我该如何实现?

How is the best way to solve this problem? 解决此问题的最佳方法是什么?

Since 以来

setDetails(string setDVDTitle, string setDVDAuthor, string setDVDReleaseDate, string setDVDCopyright, string setDVDGenre, string setDVDStatus, int setDVDRunningTime, string setDVDDirector, string setDVDStudio, string setDVDProducer)

only makes sense for a DVD object, and 仅对DVD对象有意义,并且

setDetails(string setBookTitle, string setBookAuthor, string setBookReleaseDate, string setBookCopyright, string setBookGenre, string setBookStatus, int setBookISBN)

only makes sense for a Book, the methods shouldn't be virtual , nor in the base class. 只对Book有意义,方法不应该是virtual ,也不应该在基类中。

Say I give you a LibItem* and I tell you to set its details. 假设我给您一个LibItem* ,我告诉您设置其详细信息。 What do you do? 你是做什么? Does it make sense to set its details, since they differ from one concrete implementing class to another? 设置详细信息是否有意义,因为它们从一个具体的实现类到另一个实现类都不同?

The base class should only have the method that sets: 基类仅应具有设置以下内容的方法:

string Title;
string ReleaseDate;
string Author;
string Copyright;
string Genre;
string Status;

which shouldn't be virtual , since its behavior doesn't change from implementation to implementation, and you should set specific details on the implementing classes themselves. 它不应该是virtual ,因为它的行为在实现之间不会改变,因此您应该在实现类本身上设置特定的详细信息。

The abstract base class can only contain functions that are common to all derived classes, so if you need different functions in different derived classes, they can't go in the base class. 抽象基类只能包含所有派生类共有的函数,因此,如果您需要不同派生类中的不同函数,则不能将它们引入基类。

You could downcast to get the derived type, and access its type-specific functions: 您可以向下转换以获得派生类型,并访问其特定于类型的功能:

LibItem & item = some_item();

if (Book * book = dynamic_cast<Book*>(&item)) {
    book->setDetails(book_details);
} else if (DVD * dvd = dynamic_cast<DVD*>(&item)) {
    dvd->setDetails(dvd_details);
}

If you have many different types, and many type-specific operations, then it might be worth considering the Visitor pattern ; 如果您有许多不同的类型,并且有许多特定于类型的操作,那么可能值得考虑Visitor模式 but that's overkill in most situations. 但这在大多数情况下都太过分了。

you cant, you need common interface. 您不能,您需要通用界面。 http://www.tutorialspoint.com/cplusplus/cpp_interfaces.htm . http://www.tutorialspoint.com/cplusplus/cpp_interfaces.htm This article will help you a lot in understanding of abstract classes. 本文将对您理解抽象类有很多帮助。 Member function which has different arguments for different childs shouldnt be virtual. 对于不同子对象具有不同参数的成员函数不应该是虚拟的。

Looking into your code: 查看您的代码:

try to change your arguments type from "string" to "const string&" you will avoid copies. 尝试将参数类型从“ string”更改为“ const string&”,您将避免复制。

virtual void LibItem::setDetails() = 0;

and

void Book::setDetails(string setBookTitle, string setBookAuthor, string setBookReleaseDate, string setBookCopyright, string setBookGenre, string setBookStatus, int setBookISBN)

and

void DVD::setDetails(string setDVDTitle, string setDVDAuthor, string setDVDReleaseDate, string setDVDCopyright, string setDVDGenre, string setDVDStatus, int setDVDRunningTime, string setDVDDirector, string setDVDStudio, string setDVDProducer)

are different methods, so, there is no overloading in your code. 是不同的方法,因此,代码中没有重载。

BTW. 顺便说一句。 Don't forget about virtual destructor in your LibItem... 不要忘了LibItem中的虚拟析构函数...

There are two ways you could handle this. 有两种方法可以解决此问题。 The first involves varargs, declaring the interface in the base to be setDetails( std::string const& title... ) . 第一个涉及varargs,在基础中声明接口为setDetails( std::string const& title... ) I will not go further into this way, however, as it is a sure path to unexplained crashes later down the road. 但是,我将不做进一步的介绍,因为这是以后无法解释的崩溃的必经之路。 The other solution is to use something like: setDetails( std::map< std::string, std::string > const& ) , and in the concrete implementation extract the details you want by name. 另一种解决方案是使用类似: setDetails( std::map< std::string, std::string > const& ) ,并在具体实现中按名称提取所需的详细信息。 Even then, I'm not sure it's a good solution, since given a LibItem* , you don't know what to put in the map. 即使那样,我也不知道这是一个好的解决方案,因为给定了LibItem* ,您不知道要在地图中放置什么。 (It could be a valid solution if you get the type of object and the list of details from the user. Even then, I'd probably encapsulate this into a factory function, which would know the type it is creating, verify that the details correspond, and then pass all of the details to the constructor.) 如果您从用户那里获得对象的类型和详细信息列表,这可能是一个有效的解决方案。即使如此,我也可能会将其封装到一个工厂函数中,该函数将知道其创建的类型,并验证详细信息对应,然后将所有详细信息传递给构造函数。)

And while I'm at it: you can't use an int for ISBN. 当我在使用它时:ISBN不能使用int The most reasonable representation is a string. 最合理的表示形式是字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我如何定义一个纯抽象基础 class - How can i define a pure abstract base class 我可以在抽象基类中定义构造函数吗? - Can I define a constructor in an abstract base class? 如何在基本抽象类中调用重载运算符? - How should I call an overloaded operator in a base abstract class? 当我定义一个子类以抽象出基类的构造函数的细节时,这叫什么? - What's it called when I define a subclass just to abstract away the details of the base class's constructor? 抽象基类虚拟纯方法,以自身为参数 - Abstract base class virtual pure method that takes itself as a parameter 如何使用类型特征来定义部分抽象的模板基类? - How to use type traits to define a partially abstract template base class? 调用基类方法(如果不是抽象的话) - Call base class method if not abstract 如何使用协变参数覆盖函数(在抽象基类中) - how to override a function (in an abstract base class) with a covariant parameter 定义抽象基类的默认构造函数 - Define default constructor for abstract base class 抽象基类:如何为包含指向(抽象)基类的指针的类定义复制构造函数或赋值运算符? - Abstract Base Classes: How do you define a copy constructor or assignment operator for a class that contains a pointer to a (abstract) base class?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM