C++ primer (3) —— 多态

网友投稿 298 2022-09-01

C++ primer (3) —— 多态

一 类

类的访问修饰符 只有类和友元函数可以访问私有成员 保护成员比私有成员的开放性要更大一点,可以被子类访问 友元函数定义在类的外部,可以访问类的私有成员

内联函数 如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。 在类定义中的定义的函数都是内联函数。

this指针 this指针是成员函数的隐含参数,友元不是类的成员函数,所以友元函数没有this指针。

二 访问控制和继承

访问

public

protected

private

同一个类

yes

yes

yes

派生类

yes

yes

no

外部的类

yes

no

no

派生类不会继承基类的这些方法: 析构函数,构造函数,拷贝构造函数;友元函数;重载运算符。

使用不同访问修饰符的继承特点: 公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。 保护继承(protected):当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。 私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。

多继承的格式:

class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…

例如:

#include using namespace std;class shape1{ protected: int length, width; public: shape1(int val1 = 0,int val2 = 0){ length = val1; width = val2; } int getLen(){ return (length + width) * 2; }};class shape2{ public: int getArea(int length, int width){ return length * width; }};class drive:public shape1,public shape2{ // in most cases, we use public constructor function. public: drive(int val1 = 0,int val2 = 0):shape1(val1,val2){}};int main(){ drive entity(10,20); printf("the area is %d, length is %d\n",entity.getArea(10,20),entity.getLen()); return 0;}/* the area is 200, length is 60 */

protected可以被该类的方法和其友元函数访问,不能被该类的对象访问

三 重载运算符

写作格式:​​Box operator运算符(const Box&);​​​ 不可重载的运算符: :: .* . ?: 例子: 代码:

#include #include using namespace std;class Vector{ private: int x,y; public: void show(){ printf("(x, y) is (%d, %d)\n",x,y); } Vector(int a,int b){ x=a; y=b; } Vector operator+(const Vector& other){ Vector ans(0,0); ans.x = this->x+other.x; ans.y = this->y+other.y; return ans; } Vector operator-(const Vector& other){ Vector ans(0,0); ans.x = this->x-other.x; ans.y = this->y-other.y; return ans; } int operator*(const Vector& other){ // * replace ·, dot product(数量积): a·b=a1b1+a2b2+……+anbn return this->x*other.x + this->y*other.y; } int operator^(const Vector& other){ // ^ replace x, cross product(向量积): return this->x*other.y - this->y*other.x; }};int main(){ Vector ve1(0,4); Vector ve2(5,0); Vector ans = ve1+ve2; cout<<"for sum, "; ans.show(); ans = ve1-ve2; cout<<"for sub, "; ans.show(); cout<<"for dot product, result is "<<(ve1*ve2)<

执行:

for sum, (x, y) is (5, 4)for sub, (x, y) is (-5, 4)for dot product, result is 0for cross product, result is -20

四 多态

关键词:虚函数。动态链接,后期绑定。

#include using namespace std;class father{ public: virtual void show(){ // virtual 使得编译器看指针的内容,而不是指针的类型。 puts("I'm father"); }};class son1:public father{ public: void show(){ puts("I'm son1"); }};class son2:public father{ public: void show(){ puts("I'm son2"); }};int main(){ father *p = NULL; son1 entity1; son2 entity2; p = &entity1; p->show(); p = &entity2; p->show(); return 0;}

执行:

I'm son1I'm son2

我们可以使用纯虚函数,不给出父类的show的函数体。 即是​​​virtual void show() = 0;​​

五 抽象类

六 类的其他补充内容

类的私有内部表示被称为是封装的(encapsulated) 而类的公有部分被称为类接口(class interface) 除了静态(static)数据成员外,数据成员不能在类体中被显式地初始化。 如果没有指定访问修饰符,在缺省的情况下定为private。 友元机制允许一个类授权其他的函数访问它的非公有成员。不受public private 和protected的影响。例如:

class Screen {friend istream&operator>>( istream&, Screen& );friend ostream&operator<< ( ostream&, const Screen& );public:// ...

在使一个类成为友元时,友元类的所有成员函数都被给予访问授权友谊的类的非公有成员的权力. 一个类不能有自身类型的数据成员,可以用指向自身类型的指针或引用作为数据成员. 一个对象可以被同一类类型的另一个对象初始化或赋值.

Screen *ptr = new Screen;//Screen是一个类...

new表达式返回对象的地址。

string *ps=new string; delete ps; //释放ps指向的string对象还给空闲存储区。int *p=new int[10]; delete

七 函数模版

函数模板提供一个种用来自动生成各种类型函数实例的算法 宏替换的缺陷:

#defineint main() { int a=3,b=5; a= myMin(a++,b++); cout<

函数模板的优势:

template Type myMin( Type a, Type b ) { return a < b ? a : b;}int main() { int a=3,b=5; cout<

template type sum(type a[],int len){ type s=0; for(int i=0;i

template Type min( Type (&r_array)[len] ) // (&r_array)[len] --- what ?{ Type min_val = r_array[0]; for ( int i = 1; i < len; ++i ) if ( r_array[i] < min_val ) min_val = r_array[i]; return min_val;}int ia[] = { 10, 7, 14, 3, 25 };double da[6] = { 10.2, 7.1, 14.5, 3.2, 25.0, 16.8 };int main(){ cout<

显式模板实参 改变模板实参推演机制,模板实参被显式指定在逗号分隔的列表中并使用显式指定,用尖括号括起来。紧跟在函数模板实例的名字后面 我们希望定义一个名为sum()的函数模板以便从该模板实例化的函数可以返回某一种类型的值该类型足够大可以装下两种以任何顺序传递来的任何类型 的两个值的和。

template ??? sum( T, U );char ch; unsigned int ui;// T 和U 都不用作返回类型sum( ch, ui ); // ok: U sum( T, U );sum( ui, ch ); // ok: T sum( T, U );一种方案是通过引入第三个模板参数来指明函数模板的返回类型// T1 不出现在函数模板参数表中template

C++ 模板编译模式: C++ 支持两种模板编译模式包含模式(Inclusion Model) 和分离模式(Separation Model) 包含模式:模板定义放在头文件中 真正的实例化动作发生在何时何地要取决于具体的编译器实现. min.h:

#ifndef MIN_H_INCLUDED#define MIN_H_INCLUDEDtemplate Type mymin(Type t1,Type t2){ return t1

main.cpp:

#include #include "min.h"using namespace std;int main(){ int a0=12,b0=34; double a1=12.3,b1=12.67; cout<

min.h:

#ifndef MIN_H_INCLUDED#define MIN_H_INCLUDEDtemplate Type mymin(Type t1,Type t2);#endif // MIN_H_INCLUDED

define.cpp:

export template Type mymin(Type t1,Type t2){ return t1

main.cpp:

#include #include "min.h"#include "define.cpp"using namespace std;int main(){ int a0=12,b0=34; double a1=12.3,b1=12.67; cout<(a1,b1)<

支持分离模式需要更复杂的程序设计环境, 所以它们不能在所有C++编译器实现中提供. 跨文本调用函数:

min.h:

#ifndef MIN_H_INCLUDED#define MIN_H_INCLUDEDtemplate type mymin(type t1,type t2){ return t1

min.cpp:

#include void another() { puts("this is a statement from another file.");}

main.cpp:

#include #include "min.h"#include "another.cpp"using namespace std;int main(){ char s1='a',s2='d'; cout<(s1,s2)<

模板函数的重载:

#include using namespace std;template class Array{public: type *element; int length; Array(int len){ element=new type[len]; length=len; } ~Array(){ delete element; } void show(){ for(int i=0;itype mymin(type t1,type t2){ return t1type mymin(Array ar){ type minm=1<<30; for(int i=0;i intA(10); Array douA(10); for(int i=1;i<11;i++){ intA.element[i-1]=i; douA.element[i-1]=i*1.1; } intA.show(); douA.show(); cout<

调用可以被解析为函数模板的实例或者被解析为普通函数,到底调用哪个函数取决于这些函数中的哪一个与函数实参类型匹配得最好。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:杂记 (6) —— vim, gcc, gdb, man
下一篇:如何开展网络营销?网络营销的优势有哪些?(什么是网络营销的优势)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~