Polymorphism in C++

后端 未结 7 895
甜味超标
甜味超标 2020-11-22 09:01

AFAIK:

C++ provides three different types of polymorphism.

  • Virtual functions
  • Function name overloading
  • Operator overloading
7条回答
  •  忘了有多久
    2020-11-22 09:39

    This may not be of any help, but I made this to introduce my friends to programming by giving out defined functions, like START, and END for the main function so it was not too daunting (they only used the main.cpp file). It contains Polymorphic classes and structs, templates, vectors, arrays, preproccessor directives, friendship, operators and pointers (all of which you should probably know before attempting polymorphism):

    Note: It is not finished, but you can get the idea

    main.cpp

    #include "main.h"
    #define ON_ERROR_CLEAR_SCREEN false
    START
        Library MyLibrary;
        Book MyBook("My Book", "Me");
        MyBook.Summarize();
        MyBook += "Hello World";
        MyBook += "HI";
        MyBook.EditAuthor("Joe");
        MyBook.EditName("Hello Book");
        MyBook.Summarize();
        FixedBookCollection FBooks("Fairytale Books");
        FairyTale MyTale("Tale", "Joe");
        FBooks += MyTale;
        BookCollection E("E");
        MyLibrary += E;
        MyLibrary += FBooks;
        MyLibrary.Summarize();
        MyLibrary -= FBooks;
        MyLibrary.Summarize();
        FixedSizeBookCollection<5> Collection("My Fixed Size Collection");
        /* Extension Work */ Book* Duplicate = MyLibrary.DuplicateBook(&MyBook);
        /* Extension Work */ Duplicate->Summarize();
    END
    

    main.h

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #ifndef __cplusplus
    #error Not C++
    #endif
    #define START int main(void)try{
    #define END GET_ENTER_EXIT return(0);}catch(const std::exception& e){if(ON_ERROR_CLEAR_SCREEN){system("cls");}std::cerr << "Error: " << e.what() << std::endl; GET_ENTER_EXIT return (1);}
    #define GET_ENTER_EXIT std::cout << "Press enter to exit" << std::endl; getchar();
    class Book;
    class Library;
    typedef std::vector Books;
    bool sContains(const std::string s, const char c){
        return (s.find(c) != std::string::npos);
    }
    bool approve(std::string s){
        return (!sContains(s, '#') && !sContains(s, '%') && !sContains(s, '~'));
    }
    template  bool isBook(){
        return (typeid(C) == typeid(Book) || std::is_base_of());
    }
    template class DuplicatableClass{ 
    public:
        ClassToDuplicate* Duplicate(ClassToDuplicate ToDuplicate){
            return new ClassToDuplicate(ToDuplicate);
        }
    };
    class Book : private DuplicatableClass{
    friend class Library;
    friend struct BookCollection;
    public:
        Book(const char* Name, const char* Author) : name_(Name), author_(Author){}
        void operator+=(const char* Page){
            pages_.push_back(Page);
        }
        void EditAuthor(const char* AuthorName){
            if(approve(AuthorName)){
                author_ = AuthorName;
            }
            else{
                std::ostringstream errorMessage;
                errorMessage << "The author of the book " << name_ << " could not be changed as it was not approved";
                throw std::exception(errorMessage.str().c_str());
            }
        }
        void EditName(const char* Name){
            if(approve(Name)){
                name_ = Name;
            }
            else{
                std::ostringstream errorMessage;
                errorMessage << "The name of the book " << name_ << " could not be changed as it was not approved";
                throw std::exception(errorMessage.str().c_str());
            }
        }
        virtual void Summarize(){
            std::cout << "Book called " << name_ << "; written by " << author_ << ". Contains "
                << pages_.size() << ((pages_.size() == 1) ? " page:" : ((pages_.size() > 0) ? " pages:" : " pages")) << std::endl;
            if(pages_.size() > 0){
                ListPages(std::cout);
            }
        }
    private:
        std::vector pages_;
        const char* name_;
        const char* author_;
        void ListPages(std::ostream& output){
            for(int i = 0; i < pages_.size(); ++i){
                output << pages_[i] << std::endl;
            }
        }
    };
    class FairyTale : public Book{
    public:
        FairyTale(const char* Name, const char* Author) : Book(Name, Author){}
    };
    struct BookCollection{
    friend class Library;
        BookCollection(const char* Name) : name_(Name){}
        virtual void operator+=(const Book& Book)try{
            Collection.push_back(&Book); 
        }catch(const std::exception& e){
            std::ostringstream errorMessage;
            errorMessage << e.what() << " - on line (approx.) " << (__LINE__ -3);
            throw std::exception(errorMessage.str().c_str());
        }
        virtual void operator-=(const Book& Book){
            for(int i = 0; i < Collection.size(); ++i){
                if(Collection[i] == &Book){
                    Collection.erase(Collection.begin() + i);
                    return;
                }
            }
            std::ostringstream errorMessage;
            errorMessage << "The Book " << Book.name_ << " was not found, and therefore cannot be erased";
            throw std::exception(errorMessage.str().c_str());
        }
    private:
        const char* name_;
        Books Collection;
    };
    template struct FixedBookCollection : public BookCollection{
        FixedBookCollection(const char* Name) : BookCollection(Name){
            if(!isBook()){
                std::ostringstream errorMessage;
                errorMessage << "The type " << typeid(FixedType).name() << " cannot be initialized as a FixedBookCollection";
                throw std::exception(errorMessage.str().c_str());
                delete this;
            }
        }
        void operator+=(const FixedType& Book)try{
            Collection.push_back(&Book); 
        }catch(const std::exception& e){
            std::ostringstream errorMessage;
            errorMessage << e.what() << " - on line (approx.) " << (__LINE__ -3);
            throw std::exception(errorMessage.str().c_str());
        }
        void operator-=(const FixedType& Book){
            for(int i = 0; i < Collection.size(); ++i){
                if(Collection[i] == &Book){
                    Collection.erase(Collection.begin() + i);
                    return;
                }
            }
            std::ostringstream errorMessage;
            errorMessage << "The Book " << Book.name_ << " was not found, and therefore cannot be erased";
            throw std::exception(errorMessage.str().c_str());
        }
    private:
        std::vector Collection;
    };
    template struct FixedSizeBookCollection : private std::array{
        FixedSizeBookCollection(const char* Name) : name_(Name){ if(Size < 1){ throw std::exception("A fixed size book collection cannot be smaller than 1"); currentPos = 0; } }
        void operator+=(const Book& Book)try{
            if(currentPos + 1 > Size){
                std::ostringstream errorMessage;
                errorMessage << "The FixedSizeBookCollection " << name_ << "'s size capacity has been overfilled";
                throw std::exception(errorMessage.str().c_str());
            }
            this->at(currentPos++) = &Book;
        }catch(const std::exception& e){
            std::ostringstream errorMessage;
            errorMessage << e.what() << " - on line (approx.) " << (__LINE__ -3);
            throw std::exception(errorMessage.str().c_str());
        }
    private:
        const char* name_;
        int currentPos;
    };
    class Library : private std::vector{
    public:
        void operator+=(const BookCollection& Collection){
            for(int i = 0; i < size(); ++i){
                if((*this)[i] == &Collection){
                    std::ostringstream errorMessage;
                    errorMessage << "The BookCollection " << Collection.name_ << " was already in the library, and therefore cannot be added";
                    throw std::exception(errorMessage.str().c_str());
                }
            }
            push_back(&Collection);
        }
        void operator-=(const BookCollection& Collection){
            for(int i = 0; i < size(); ++i){
                if((*this)[i] == &Collection){
                    erase(begin() + i);
                    return;
                }
            }
            std::ostringstream errorMessage;
            errorMessage << "The BookCollection " << Collection.name_ << " was not found, and therefore cannot be erased";
            throw std::exception(errorMessage.str().c_str());
        }
        Book* DuplicateBook(Book* Book)const{
            return (Book->Duplicate(*Book));
        }
        void Summarize(){
            std::cout << "Library, containing " << size() << ((size() == 1) ? " book collection:" : ((size() > 0) ? " book collections:" : " book collections")) << std::endl;
            if(size() > 0){
                for(int i = 0; i < size(); ++i){
                    std::cout << (*this)[i]->name_ << std::endl;
                }
            }
        }
    };
    

提交回复
热议问题