AFAIK:
C++提供了三种不同类型的多态性。
除了上述三种类型的多态性之外,还有其他类型的多态性:
我知道运行时多态可以通过虚拟函数来实现,静态多态性可以通过模板函数来实现。
但另外两个人
ad多态性:
如果可以使用的实际类型的范围是有限的,并且必须在使用之前单独指定组合,则这称为ad多态性。
参数多态性:
如果所有代码都是在没有提到任何特定类型的情况下编写的,并且因此可以与任意数量的新类型一起透明地使用,则称为参数多态。
我几乎听不懂。
如果可能的话,有人能用一个例子来解释这两个问题吗?我希望这些问题的答案将有助于许多新的学生通过考试。
发布于 2013-11-17 08:15:41
在C++中,重要的区别是运行时与编译时绑定。正如我稍后将解释的那样,即席与参数化并没有真正的帮助。
|----------------------+--------------|
| Form | Resolved at |
|----------------------+--------------|
| function overloading | compile-time |
| operator overloading | compile-time |
| templates | compile-time |
| virtual methods | run-time |
|----------------------+--------------|
注释运行时多态仍然可以在编译时解析,但这只是优化。需要高效地支持运行时解决方案,并与其他问题进行权衡,是导致虚拟函数成为其本质的部分原因。对于C++中的所有形式的多态性来说,这都是关键--每种多态性都来自于在不同的环境中进行的不同的权衡。
函数重载和操作符重载在所有重要方面都是相同的。使用它们的名称和语法不影响多态性。
模板允许您一次指定许多函数重载。
同样的分辨率-时间概念还有另外一组名字.
|---------------+--------------|
| early binding | compile-time |
| late binding | run-time |
|---------------+--------------|
这些名称更多地与OOP相关联,因此说模板或其他非会员函数使用早期绑定有点奇怪。
为了更好地理解虚拟函数和函数重载之间的关系,理解“单调度”和“多调度”的区别也是非常有用的。这个想法可以理解为一个进步..。
显然,OOP不仅仅是将一个参数指定为特殊参数的借口,但这是其中的一部分。回到我所说的权衡--单一调度非常容易高效地完成(通常的实现称为“虚拟表”)。多分派不仅在效率方面更尴尬,而且对于单独编译也是如此。如果你好奇的话,你可能会查到“表达问题”。
正如对非成员函数使用“早期绑定”一词有点奇怪一样,在编译时使用“单次分派”和“多重分派”这两个术语也有点奇怪。通常,C++被认为没有多个调度,这被认为是一种特殊的运行时解决方案。然而,函数重载可以看作是在编译时完成的多个分派。
回到参数和即席多态之间,这些术语在函数式编程中更流行,在C++中不太适用。即便如此..。
参数多态意味着您将类型作为参数,并且无论您对这些参数使用何种类型,都使用完全相同的代码。
ad多态性是指根据特定类型提供不同的代码。
重载和虚拟函数都是即席多态的例子。
又有几个同义词..。
|------------+---------------|
| parametric | unconstrained |
| ad-hoc | constrained |
|------------+---------------|
不过,这些不是完全同义词,尽管它们通常被当作是同义词,这也是C++中可能出现混淆的地方。
将这些作为同义词处理的理由是,通过将多态性限制到特定类型类,就可以使用特定于这些类型类的操作。此处的"classes“一词可以从OOP的意义上解释,但实际上只是指(通常是命名的)一组共享某些操作的类型。
因此,参数多态性通常被认为(至少在默认情况下)意味着不受约束的多态性。因为不管类型参数如何,都使用相同的代码,所以唯一可支持的操作是那些对所有类型都有效的操作。通过不受约束地设置类型集,可以严格限制可应用于这些类型的操作集。
例如,Haskell,你可以.
myfunc1 :: Bool -> a -> a -> a
myfunc1 c x y = if c then x else y
这里的a
是一种无约束的多态类型。它可能是任何东西,所以我们对这种类型的值无能为力。
myfunc2 :: Num a => a -> a
myfunc2 x = x + 3
在这里,a
被限制为Num
类的成员--它们的作用类似于数字。该约束允许您使用这些值执行数字操作,例如添加它们。即使是3
也是多态类型推断,表明您指的是a
类型的3
。
我认为这是受约束的参数多态性。只有一个实现,但只能在受约束的情况下应用。ad方面是+
和3
使用的选择。Num
的每个“实例”都有自己独特的实现。所以,即使在Haskell中,“参数化”和“无约束”也不是真正的同义词--别怪我,这不是我的错!
在C++中,重载和虚拟函数都是即席多态.ad多态性的定义并不关心实现是在运行时选择还是在编译时选择。
如果每个模板参数都具有typename
类型,则typename
非常接近于模板的参数多态性。有类型参数,不管使用哪种类型,都有一个实现。然而,“替换失败不是错误”规则意味着由于在模板中使用操作而产生隐式约束。其他复杂因素包括模板专门化以提供替代模板--不同的(特别的)实现。
因此,在某种程度上,C++具有参数多态,但它是隐式约束的,并且可能被特殊的替代品所覆盖--也就是说,这种分类对于C++并不有效。
发布于 2011-05-02 07:44:35
至于ad多态性,它意味着函数重载或操作符重载.请看这里:
多态
至于参数多态,模板函数也可以计算在内,因为它们不一定接受固定类型的参数。例如,一个函数可以对整数数组进行排序,也可以对字符串数组进行排序,等等。
多态
发布于 2013-12-27 18:45:40
这可能没有任何帮助,但我这样做是为了向我的朋友介绍编程,我给出了定义的函数,比如START
,以及主函数的END
,这样就不会太让人望而生畏(他们只使用main.cpp文件)。它包含多态类和结构、模板、向量、数组、预处理器指令、友谊、运算符和指针(在尝试多态之前,您可能应该知道所有这些):
备注:它还没有完成,但是您可以得到的想法
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<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
main.h
#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;
}
}
}
};
https://stackoverflow.com/questions/5854581
复制相似问题