Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C+多态性+;_C++_Polymorphism_C++ Faq - Fatal编程技术网

C++ C+多态性+;

C++ C+多态性+;,c++,polymorphism,c++-faq,C++,Polymorphism,C++ Faq,阿法克: C++提供了三种不同类型的多态性 虚拟函数 函数名重载 运算符重载 除了上述三种类型的多态性外,还有其他类型的多态性: 运行时 编译时 特设多态性 参数多态性 我知道运行时多态性可以通过虚拟函数实现 静态多态性可以通过模板函数实现 但是对于另外两个 特设多态性 参数多态性 这个, 特殊多态性: 如果可以使用的实际类型的范围是有限的,并且在使用之前必须单独指定组合,则这称为ad-hoc多态性 参数多态性: 如果所有代码都是在没有提及任何特定类型的情况下编写的,因此可以透明地与

阿法克:

C++提供了三种不同类型的多态性

  • 虚拟函数
  • 函数名重载
  • 运算符重载
除了上述三种类型的多态性外,还有其他类型的多态性:

  • 运行时
  • 编译时
  • 特设多态性
  • 参数多态性
我知道运行时多态性可以通过虚拟函数实现 静态多态性可以通过模板函数实现

但是对于另外两个

  • 特设多态性
  • 参数多态性 这个,
特殊多态性:

如果可以使用的实际类型的范围是有限的,并且在使用之前必须单独指定组合,则这称为ad-hoc多态性

参数多态性:

如果所有代码都是在没有提及任何特定类型的情况下编写的,因此可以透明地与任何数量的新类型一起使用,则称为参数多态性

我几乎无法理解:(

如果可能的话,有人能用一个例子来解释这两个问题吗?
我希望这些问题的答案能对他们学校的许多新学生有所帮助。

至于特殊多态性,它意味着函数重载或运算符重载。请查看此处:

至于参数多态性,模板函数也可以计算在内,因为它们不一定接受固定类型的参数。例如,一个函数可以对整数数组进行排序,也可以对字符串数组进行排序,等等

对多态性的理解/要求 要理解多态性——正如计算科学中使用的术语一样——从简单的测试和定义开始有助于理解多态性。考虑:

    Type1 x;
    Type2 y;

    f(x);
    f(y);
这里,
f()
将执行一些操作,并将给定值
x
y
作为输入

若要显示多态性,
f()
必须能够使用至少两种不同类型的值(例如
int
double
),查找并执行不同类型的适当代码


多态性的C++机制 显式程序员指定多态性 您可以编写
f()
,以便它可以通过以下任一方式对多种类型进行操作:

  • 预处理:

    #define f(X) ((X) += 2)
    // (note: in real code, use a longer uppercase name for a macro!)
    
  • 超载:

    void f(int& x)    { x += 2; }
    
    void f(double& x) { x += 2; }
    
  • 模板:

    template <typename T>
    void f(T& x) { x += 2; }
    
其他相关机制 编译器为内置类型、标准转换和强制转换提供的多态性将在后面讨论,以确保完整性,如下所示:

  • 他们通常都是凭直觉理解的(保证会有“哦,那”的反应)
  • 它们影响要求上述机制的门槛和使用的无缝性,以及
  • 解释是从更重要的概念中巧妙地转移注意力
术语 进一步分类 鉴于上述多态机制,我们可以用不同的方式对其进行分类:

  • 何时选择多态类型特定的代码

    • 运行时意味着编译器必须为程序运行时可能处理的所有类型生成代码,并且在运行时选择正确的代码(虚拟分派)
    • 编译时意味着在编译过程中选择特定类型的代码。其结果是:假设一个程序只调用上面带有
      int
      参数的
      f
      ——根据使用的多态机制和内联选择,编译器可能会避免为
      f(双精度)生成任何代码
      ,或者生成的代码可能在编译或链接过程中的某个时刻被丢弃。(除虚拟分派外,上述所有机制)

  • 支持哪些类型

    • Ad hoc意思是您提供明确的代码来支持每种类型(例如重载、模板专业化);您明确地添加了对“this”(根据Ad hoc的意思)类型、其他一些“this”以及“that”类型的支持;-)
    • 参数化意味着您可以尝试对各种参数类型使用该函数,而无需专门执行任何操作来启用其支持(例如模板、宏)。具有与模板/宏expects1类似的函数/运算符的对象是模板/宏执行其工作所需的全部内容,具体类型与此无关。C++20引入的“概念”表达并实现了这些期望-请参阅

      • 参数多态性提供了鸭子类型——詹姆斯·惠特科姆·赖利(James Whitcom Riley)提出的一个概念,他显然说过“当我看到一只鸟像鸭子一样走路,像鸭子一样游泳,像鸭子一样呱呱叫,我就把它叫做鸭子。”

        编译器为基本类型提供的重载在高级(3GL+)计算机语言中很常见,对多态性的明确讨论通常意味着更多。(2GLs—汇编语言—通常要求程序员对不同类型显式使用不同的助记符。)

        >标准转换

        C++标准的第四节描述标准转换。< /P> 第一点很好地总结了(来自一份旧草案——希望仍然基本正确):

        -1-标准转换是为内置类型定义的隐式转换。子句conv枚举此类转换的完整集合。标准转换序列是按以下顺序进行的标准转换序列:

        • 以下集合的零或一个转换:左值到右值转换、数组到指针转换和函数到指针转换

        • 以下集合中的零或一个转换:整数提升、浮点提升、整数转换、浮点转换、浮点整数转换、指针转换、指向成员的指针
          struct Base { virtual Base& operator+=(int) = 0; };
          
          struct X : Base
          {
              X(int n) : n_(n) { }
              X& operator+=(int n) { n_ += n; return *this; }
              int n_;
          };
          
          struct Y : Base
          {
              Y(double n) : n_(n) { }
              Y& operator+=(int n) { n_ += n; return *this; }
              double n_;
          };
          
          void f(Base& x) { x += 2; } // run-time polymorphic dispatch
          
          template <typename Duck>
          void do_ducky_stuff(const Duck& x) { x.walk().swim().quack(); }
          
          do_ducky_stuff(Vilified_Cygnet());
          
          std::string x;
          int y = 0;
          
          x += 'c';
          y += 'c';
          
          double a(double x) { return x + 2; }
          
          a(3.14);
          a(42);
          
          int a, b;
          
          if (std::cin >> a >> b)
              f(a, b);
          
          f(const std::string& x);
          f("hello");  // invokes `std::string::string(const char*)`
          
          void f()
          {
              typedef int Amount;
              Amount x = 13;
              x /= 2;
              std::cout << x * 1.1;
          }
          
          void f()                               void f()
          {                                      {
              typedef int Amount;                    typedef double Amount;
              Amount x = 13;                         Amount x = 13.0;
              x /= 2;                                x /= 2.0;
              std::cout << double(x) * 1.1;          std::cout << x * 1.1;
          }                                      }
          
          template <typename Amount>
          void f()
          {
              Amount x = 13;
              x /= 2;
              std::cout << x * 1.1;
          }
          
          template <typename Amount, typename Policy>
          void f()
          {
              Amount x = Policy::thirteen;
              x /= static_cast<Amount>(2);
              std::cout << traits<Amount>::to_double(x) * 1.1;
          }
          
          |----------------------+--------------|
          | Form                 | Resolved at  |
          |----------------------+--------------|
          | function overloading | compile-time |
          | operator overloading | compile-time |
          | templates            | compile-time |
          | virtual methods      | run-time     |
          |----------------------+--------------|
          
          |---------------+--------------|
          | early binding | compile-time |
          | late binding  | run-time     |
          |---------------+--------------|
          
          |------------+---------------|
          | parametric | unconstrained |
          | ad-hoc     | constrained   |
          |------------+---------------|
          
          myfunc1 :: Bool -> a -> a -> a
          myfunc1 c x y = if c then x else y
          
          myfunc2 :: Num a => a -> a
          myfunc2 x = x + 3
          
          #include <iostream>
          
          class Animal{
          public:
             Animal(const char* Name) : name_(Name){/* Add any method you would like to perform here*/
              virtual void Speak(){
                  std::cout << "I am an animal called " << name_ << std::endl;
              }
              const char* name_;
          };
          
          class Dog : public Animal{
          public:
              Dog(const char* Name) : Animal(Name) {/*...*/}
              void Speak(){
                  std::cout << "I am a dog called " << name_ << std::endl;
              }
          };
          
          int main(void){
              Animal Bob("Bob");
              Dog Steve("Steve");
              Bob.Speak();
              Steve.Speak();
              //return (0);
          }
          
          #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<FairyTale> 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
          
          #include <iostream>
          #include <sstream>
          #include <vector>
          #include <string>
          #include <type_traits>
          #include <array>
          #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<const Book*> 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 <class C> bool isBook(){
              return (typeid(C) == typeid(Book) || std::is_base_of<Book, C>());
          }
          template<class ClassToDuplicate> class DuplicatableClass{ 
          public:
              ClassToDuplicate* Duplicate(ClassToDuplicate ToDuplicate){
                  return new ClassToDuplicate(ToDuplicate);
              }
          };
          class Book : private DuplicatableClass<Book>{
          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<const char*> 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<class FixedType> struct FixedBookCollection : public BookCollection{
              FixedBookCollection(const char* Name) : BookCollection(Name){
                  if(!isBook<FixedType>()){
                      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<const FixedType*> Collection;
          };
          template<size_t Size> struct FixedSizeBookCollection : private std::array<const Book*, Size>{
              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<const BookCollection*>{
          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;
                      }
                  }
              }
          };
          
          The Surgeon
          The Hair Stylist
          The Actor
          
          The Surgeon would begin to make an incision.
          The Hair Stylist would begin to cut someone's hair.
          The Actor would abruptly stop acting out of the current scene, awaiting directorial guidance.