21天学通C++(第四版)笔记

21天学通C++(第四版)笔记

[@more@]

1 #include
2
3 int main()
4 {
5 std::cout << "Hello World!";
7 return 0;
8 }

会注意到,在cout和endl前面使用std::是烦人事情,可通过两种方法来搞定
第一种,在代码清单开始位置告诉编译器使用标准库函数cout和endl。
int main()
{
using std::cout;
using std::endl;
......
}
第二种,告诉编译器,使用全部的namespace标准,意为没有特殊指定的任何对象可以假定都来自标准namespace。
int main()
{
using namespace std;
......
}
可以看出,使用using namespace std;的好处是不再需要特殊指定实际使用的对象(cout和endl)

以下开始面向对象
声明一个类:
class Cat
{
unsigned int itsAge;
unsigned int itWeight;
void Meow();
};
声明这个类并没有为Cat分配内存。它只告诉编译器Cat是什么,它包含什么数据以及功能是什么。同事它该告诉编译器Cat有多大,一个整型占4个字节,那么Cat的大小为8个字节,Meow不占空间,因为系统没有为成员函数(方法)分配存储空间。

一个类的所有成员(数据和方法)默认时均为私有。私有成员只能在类本身的方法内访问。共有成员则可以被该类的所有对象访问。
作为设计的一般规则,应该保持类的成员数据为私有,所以需要创建成为访问方法的公有函数来设置和获取私有成员变量。

例子:
1 #include
2
3 using namespace std;
4
5 class cat
6 {
7 public:
8 int getage();
9 void setage(int age);
10 void meow();
11 private:
12 int itsage;
13 };
14
15 int cat::getage()
16 {
17 return itsage;
18 }
19
20 void cat::setage(int age)
21 {
22 itsage = age;
23 }
24
25 void cat::meow()
26 {
27 cout << "meow.-------------- n";
28 }
29
30 int main()
31 {
32 cat frisky;
33 frisky.setage(5);
34 frisky.meow();
35
36 cout << frisky.getage() << " years old.n";
37
38 frisky.meow();
39 return 0;
40
41 }
结果:
meow.--------------
5 years old.
meow.--------------

如果没有声明构造函数或析构函数,编译器会自动创建一个。有许多类型的构造函数,有些需要参数,有些不需要,没有参数的被称为默认构造函数。

使用构造函数和析构函数的例子:
1 #include
2
3 using namespace std;
4
5 class cat
6 {
7 public:
8 cat(int initialage);
9 ~cat();
10 int getage();
11 void setage(int age);
12 void meow();
13 private:
14 int itsage;
15 };
16
17 cat::cat(int initialage)
18 {
19 itsage = initialage;
20 }
21
22 cat::~cat()
23 {
24 }
25
26 int cat::getage()
27 {
28 return itsage;
29 }
30
31 void cat::setage(int age)
32 {
33 itsage = age;
34 }
35
36 void cat::meow()
37 {
38 cout << "----------------------n";
39 }
40
41 int main()
42 {
43 cat frisky(5);
44 frisky.meow();
45
46 cout << frisky.getage() << " years old.n";
47
48 frisky.meow();
49 frisky.setage(7);
50
51 cout << frisky.getage() << " years old.n";
52 return 0;
53 }
结果:
----------------------
5 years old.
----------------------
7 years old.

良好的编程习惯尽可能多的方法声明为const,例如:int GetAge() const;

如果将某个函数的定义放在该类的声明中,浙江使该函数自动成为内嵌函数。
class Cat
{
public:
int GetWeight(){return itsWeight;} //inline
void SetWeight(int aWeight);
};

C++使用关键字new分配自由存储区中的内存。
例如:
unsigned short int *pPointer;
pPointer = new unsigned short int;

unsigned short int *pPointer = new unsigned short int;
相对应用delete来释放内存,例如:delete pPointer;
当使用delete删除一个指针时,把它赋为0(空指针)。删除一个空指针是安全的。
在自由存储区内创建对象,例如:Cat *pCat = new Cat;

自由存储区的成员数据:例子:
1 #include
2
3 using namespace std;
4
5 class simplecat
6 {
7 public:
8 simplecat();
9 ~simplecat();
10 int getage() const {return *itsage;}
11 void setage(int age) {*itsage = age;}
12
13 int getweight() const {return *itsweight;}
14 void setweight(int weight) {*itsweight = weight;}
15 private:
16 int *itsage;
17 int *itsweight;
18 };
19
20 simplecat::simplecat()
21 {
22 itsage = new int(2);
23 itsweight = new int(5);
24 }
25
26 simplecat::~simplecat()
27 {
28 delete itsage;
29 delete itsweight;
30 }
31
32 int main()
33 {
34 simplecat *frisky = new simplecat;
35 cout << frisky->getage() << " years oldn";
36 frisky->setage(5);
37 cout << frisky->getage() << " years oldn";
38 delete frisky;
39 return 0;
40 }
结果:
2 years old
5 years old

每一个类的成员函数都有一个隐藏的参数 —— this指针,this指针职场每一个单独的对象
例子:
1 #include
2
3 using namespace std;
4
5 class rectangle
6 {
7 public:
8 rectangle();
9 ~rectangle();
10 void setlength(int length)
11 {
12 this->itslength = length;
13 }
14 int getlength() const
15 {
16 return this->itslength;
17 }
18
19 void setwidth(int width)
20 {
21 itswidth = width;
22 }
23 int getwidth() const
24 {
25 return itswidth;
26 }
27 private:
28 int itslength;
29 int itswidth;
30 };
31
32 rectangle::rectangle()
33 {
34 itswidth = 1;
35 itslength = 2;
36 }
37
38 rectangle::~rectangle()
39 {}
40
41 int main()
42 {
43 rectangle therect;
44 cout << therect.getlength() << "feet long.n";
45 cout << therect.getwidth() << "feet wide.n";
46 therect.setlength(20);
47 therect.setlength(10);
48 cout << therect.getlength() << "feet long.n";
49 cout << therect.getwidth() << "feet wide.n";
50 return 0;
51 }
结果:
2feet long.
1feet wide.
10feet long.
1feet wide.
this是一个指针,保存了一个对象的地址,即它是一个指向对象自身的指针。

一个对迷途指针的很好的比喻:如同甲公司搬家了,但是你仍然使用原来的号码,这可能不会导致什么严重后果,也许这个电话放在一个无人居住的房子里面,但如果这个号码重新分配给一个军工厂,你的电话就可能引发爆炸,摧毁整个城市。

默认复制构造函数,它在每次复制一个对象的时候调用,当按值传递对象时,无论是传递到函数内还是作为函数的返回值,均会生产该对象的一个临时拷贝。如果这个对象是一个用户定义的对象,则调用这个类的复制构造函数。所有复制构造函数均有一个参数,即对同一类的对象的引用
例子:
1 #include
2
3 using namespace std;
4
5 class cat
6 {
7 public:
8 cat();
9 cat(const cat &);
10 ~cat();
11 int getage() const {return *itsage;}
12 int getweight() const {return *itsweight;}
13 void setage(int age) {*itsage = age;}
14
15 private:
16 int *itsage;
17 int *itsweight;
18 };
19
20 cat::cat()
21 {
22 itsage = new int;
23 itsweight = new int;
24 *itsage = 5;
25 *itsweight = 9;
26 }
27
28 cat::cat(const cat & rhs) //通常用rhs来表示复制构造函数的参数
29 {
30 itsage = new int;
31 itsweight = new int;
32 *itsage = rhs.getage(); //public access
33 *itsweight = *(rhs.itsweight); //private access
34 }
35
36 cat::~cat()
37 {
38 delete itsage;
39 itsage = 0;
40 delete itsweight;
41 itsweight = 0;
42 }
43
44 int main()
45 {
46 cat frisky;
47 cout << frisky.getage() < 48 cout << frisky.getweight() < 49 cout << "nn";
50 frisky.setage(6);
51
52 cat boots(frisky);
53 cout << frisky.getage() << endl;
54 cout << frisky.getweight() < 55 cout << boots.getage() < 56 cout << boots.getweight() < 57 cout << "nn";
58
59 frisky.setage(7);
60 cout << frisky.getage() << endl;
61 cout << frisky.getweight() < 62 cout << boots.getage() < 63 cout << boots.getweight() < 64
65 return 0;
66 }
结果:
5
9


6
9
6
9


7
9
6
9

重载前置运算符
1 #include
2
3 using namespace std;
4
5 class counter
6 {
7 public:
8 counter();
9 ~counter() {}
10 int getitsval() const {return itsval;}
11 void setitsval(int x) {itsval = x;}
12 void increment() {++itsval;}
13 void operator++ () {++itsval;} //重载了operator++,
14
15 private:
16 int itsval;
17 };
18
19 counter::counter():itsval(0)
20 {}
21
22 int main()
23 {
24 counter i;
25 cout << i.getitsval() << endl;
26 i.increment();
27 cout << i.getitsval() << endl;
28 ++i;
29 cout << i.getitsval() << endl;
30
31 return 0;
32 }
结果:
0
1
2
利用 void operator++ () 语法进行重载++运算符。

继承 protected保护型,使数据对于这个类和从这个类派生出来的类是可见的。
例子:
1 #include
2
3 using namespace std;
4
5 enum BREED {GOLDEN,CAIRN,OANDIE,SHETLAND,DOBERMAN,LAB};
6
7 class Mammal
8 {
9 public:
10 Mammal();
11 ~Mammal();
12
13 int getage() const {return itsage;}
14 void setage(int age) {itsage = age;}
15 int getweight() const {return itsweight;}
16 void setweight(int weight) {itsweight = weight;}
17
18 void speak() const {cout << "++++++++++++++++n";}
19 void sleep() const {cout << "----------------n";}
20
21 protected:
22 int itsage;
23 int itsweight;
24 };
25
26 class dog : public Mammal
27 {
28 public:
29 dog();
30 ~dog();
31
32 BREED getbreed() const {return itsbreed;}
33 void setbreed(BREED breed){itsbreed = breed;}
34
35 void wagtail() const {cout << "$$$$$$$$$$$n";}
36 void begforfood() const {cout << "~~~~~~~~n";}
37
38 private:
39 BREED itsbreed;
40 };
41
42 Mammal::Mammal():itsage(1),itsweight(5)
43 {
44 cout << "Mammal constructor...n";
45 }
46
47 Mammal::~Mammal()
48 {
49 cout << "Mammal destructor...n";
50 }
51
52 dog::dog():itsbreed(GOLDEN)
53 {
54 cout << "dog constructor...n";
55 }
56
57 dog::~dog()
58 {
59 cout << "dog destructor...n";
60 }
61
62 int main()
63 {
64 dog fido;
65 printf("---------------[1]---------n");
66 fido.speak();
67 printf("---------------[2]---------n");
68 fido.wagtail();
69 printf("---------------[3]---------n");
70 cout << fido.getage() << endl;
71 printf("---------------[4]---------n");
72
73 return 0;
74 }
结果:
Mammal constructor...
dog constructor...
---------------[1]---------
++++++++++++++++
---------------[2]---------
$$$$$$$$$$$
---------------[3]---------
1
---------------[4]---------
dog destructor...
Mammal destructor...

覆盖函数:dog对象可以访问Mammal类中的所有成员函数,也可以访问dog类可能增加的任何成员函数,例如wagtail()。它还可以覆盖一个基类函数。覆盖函数意味着在派生类中改变基类函数的实现。当派生类用与基类的成员函数相同的返回值和签名,但却用新的实现方法创建一个函数时,就称为覆盖了该方法。
例子:
1 #include
2 using namespace std;
3
4 enum BREED{GOLDEN,CAIRN,DANDIE,SHETLAND,DOBERMAN,LAB};
5
6 class Mammal
7 {
8 public:
9 Mammal() {cout << "Mammal constructor...n";}
10 ~Mammal() {cout << "Mammal destructor...n";}
11
12 void speak() const {cout << "Mammal sound!n";}
13 void sleep() const {cout << "++++++++++++++n";}
14
15 protected:
16 int itsage;
17 int itsweight;
18 };
19
20 class dog:public Mammal
21 {
22 public:
23 dog(){cout << "dog constructor...n";}
24 ~dog(){cout << "dog destructor...n";}
25
26 void wagtail() const {cout << "tail wagging...n";}
27 void begforfood()const{cout << "begging for food...n";}
28 void speak() const {cout << "woof!n";}
29
30 private:
31 BREED itsbreed;
32 };
33
34 int main()
35 {
36 Mammal big;
37 dog fido;
38 big.speak();
39 fido.speak();
40
41 return 0;
42 }
结果:
Mammal constructor...
Mammal constructor...
dog constructor...
Mammal sound!
woof!
dog destructor...
Mammal destructor...
Mammal destructor...

从覆盖方法中调用基方法
1 #include
2 using namespace std;
3
4 class Mammal
5 {
6 public:
7 void move() const {cout << "----------n";}
8 void move(int distance) const
9 {
10 cout << "[1]++++++++n";
11 cout << "[2]++++++++n";
12 }
13 protected:
14 int itsage;
15 int itsweight;
16 };
17
18 class dog:public Mammal
19 {
20 public:
21 void move() const;
22 };
23
24 void dog::move() const
25 {
26 cout << "#####n";
27 Mammal::move(3);
28 }
29
30 int main()
31 {
32 Mammal big;
33 dog fido;
34
35 big.move(2);
36 fido.Mammal::move();
37 fido.move();
38
39 return 0;
40 }
结果:
[1]++++++++
[2]++++++++
----------
#####
[1]++++++++
[2]++++++++

虚函数
例子:
1 #include
2 using namespace std;
3
4 class Mammal
5 {
6 public:
7 Mammal():itsage(1) {cout << "Mammal conn";}
8 virtual ~Mammal() {cout << "Mammal des";}
9 void move() const {cout << "Mammal move -----n";}
10 virtual void speak() const {cout << "Mammal speak!n";}
11 protected:
12 int itsage;
13 };
14
15 class dog:public Mammal
16 {
17 public:
18 dog() {cout << "dog conn";}
19 virtual ~dog() {cout << "dog desn"; }
20 void wagtail() {cout << "wagging tail...n";}
21 void speak() const {cout << "woooooooooooooofn";}//由于speak是虚函数,因此调用在dog中被覆盖的speak函数
22 void move() const {cout << "dog moves 5555555555n";}
23 };
24
25 int main()
26 {
27 Mammal *pDog = new dog;
28 pDog->move();
29 pDog->speak();
30
31 return 0;
32 }
结果:
Mammal con
dog con
Mammal move -----
woooooooooooooof
虚函数只对指针和引用有效,按值传递不允许调用虚函数。类中一个函数时虚函数,那么析构函数也应该是虚函数。派生类的析构函数会自动调用基类的析构函数,结果整个对象就会正确销毁。
但构造函数不能是虚函数,也不存在虚复制构造函数

多态性
一段小程序:
1 #include
2 using namespace std;
3
4 class horse
5 {
6 public:
7 void gallop() {cout << "galloping...n";}
8 virtual void fly()
9 {
10 cout << "horses can't fly.n";
11 }
12 private:
13 int itsage;
14 };
15
16 class pegasus:public horse
17 {
18 public:
19 virtual void fly() {cout << "i can fly~~!n";}
20 };
21
22 const int num = 5;
23
24 int main()
25 {
26 horse *ranch[num];
27 horse *phorse;
28 int choice,i;
29 for(i = 0; i < num; i++)
30 {
31 cout << "(1)horse (2)pegasus : ";
32 cin >> choice;
33 if(choice == 2)
34 phorse = new pegasus;
35 else
36 phorse = new horse;
37 ranch[i] = phorse;
38 }
39
40 cout << "n";
41
42 for(i = 0; i < num; i++)
43 {
44 ranch[i]->fly();
45 delete ranch[i];
46 }
47
48 return 0;
49 }
结果:
(1)horse (2)pegasus : 2
(1)horse (2)pegasus : 1
(1)horse (2)pegasus : 2
(1)horse (2)pegasus : 2
(1)horse (2)pegasus : 1

i can fly~~!
horses can't fly.
i can fly~~!
i can fly~~!
horses can't fly.

多重继承:
1 #include
2 using namespace std;
3
4 class horse
5 {
6 public:
7 horse()
8 {
9 cout << "horse constructor...n";
10 }
11 virtual ~horse()
12 {
13 cout << "horse destructor...n";
14 }
15 virtual void whinny() const
16 {
17 cout << "whinny...n";
18 }
19 private:
20 int itsage;
21 };
22
23 class bird
24 {
25 public:
26 bird()
27 {
28 cout << "bird constructor...n";
29 }
30 virtual ~bird()
31 {
32 cout << "bird destructor...n";
33 }
34 virtual void chirp() const
35 {
36 cout << "chirp...n";
37 }
38 virtual void fly() const
39 {
40 cout << "i can fly!";
41 }
42 private:
43 int itsage;
44 };
45
46 class pegasus:public horse,public bird
47 {
48 public:
49 void chirp() const
50 {
51 whinny();
52 }
53 pegasus()
54 {
55 cout << "pegasus constructor...n";
56 }
57 ~pegasus()
58 {
59 cout << "pegasus destructor...n";
60 }
61 };
62
63 const int NUM = 2;
64
65 int main()
66 {
67 horse *ranch[NUM];
68 bird *avi[NUM];
69 horse *pHorse;
70 bird *pBird;
71 int choice,i;
72 for(i = 0; i < NUM; i++)
73 {
74 cout << "1: Horse 2: pegasus :";
75 cin >> choice;
76 if(choice == 2)
77 pHorse = new pegasus;
78 else
79 pHorse = new horse;
80 ranch[i] = pHorse;
81 }
82
83 for(i = 0; i < NUM; i++)
84 {
85 cout << "1: bird 2: pegasus :";
86 cin >> choice;
87 if(choice ==2)
88 pBird = new pegasus;
89 else
90 pBird = new bird;
91 avi[i] = pBird;
92 }
93
94 cout << "n";
95 for(i = 0; i < NUM; i++)
96 {
97 cout << "nRanch[" << i << "]:";
98 ranch[i]->whinny();
99 delete ranch[i];
100 }
101
102 for(i = 0; i < NUM; i++)
103 {
104 cout << "naviary[" << i << "]:";
105 avi[i]->chirp();
106 avi[i]->fly();
107 delete avi[i];
108 }
109 return 0;
110 }
结果:
1: Horse 2: pegasus :1
horse constructor...
1: Horse 2: pegasus :2
horse constructor...
bird constructor...
pegasus constructor...
1: bird 2: pegasus :1
bird constructor...
1: bird 2: pegasus :2
horse constructor...
bird constructor...
pegasus constructor...


Ranch[0]:whinny...
horse destructor...

Ranch[1]:whinny...
pegasus destructor...
bird destructor...
horse destructor...

aviary[0]:chirp...
i can fly!bird destructor...

aviary[1]:whinny...
i can fly!pegasus destructor...
bird destructor...
horse destructor...

多重继承对象中的构造函数
1 #include
2
3 using namespace std;
4
5 enum COLOR {red,green,blue,yellow,white,black,brown};
6
7 class horse
8 {
9 public:
10 horse(COLOR color, int height);
11 virtual ~horse()
12 {
13 cout << "horse destructor ...n";
14 }
15 virtual void whinny() const
16 {
17 cout << "whinny!...n";
18 }
19 virtual int getheight() const
20 {
21 return itsHeight;
22 }
23 virtual COLOR getcolor() const
24 {
25 return itsColor;
26 }
27 private:
28 int itsHeight;
29 COLOR itsColor;
30 };
31
32 horse::horse(COLOR color, int height):itsColor(color),itsHeight(height)
33 {
34 cout << "Horse constructor ...n";
35 }
36
37 class bird
38 {
39 public:
40 bird(COLOR color, bool migrates);
41 virtual ~bird()
42 {
43 cout << "bird destrutor ... n";
44 }
45 virtual void chirp() const
46 {
47 cout << "chirp ...n";
48 }
49 virtual void fly() const
50 {
51 cout << "i can fly!~~~~~~~~~~~~~~~~~n";
52 }
53 virtual COLOR getcolor() const
54 {
55 return itsColor;
56 }
57 virtual bool getmigration() const
58 {
59 return itsMigration;
60 }
61 private:
62 COLOR itsColor;
63 bool itsMigration;
64 };
65
66 bird::bird(COLOR color, bool migrates):itsColor(color),itsMigration(migrates)
67 {
68 cout << "bird constructor ... n";
69 }
70
71 class pegasus:public horse,public bird
72 {
73 public:
74 void chirp() const
75 {
76 whinny();
77 }
78 pegasus(COLOR,int,bool,long);
79 ~pegasus()
80 {
81 cout << "pegasus destructor ...n";
82 }
83 virtual long getnumberbelievers() const
84 {
85 return itsNumberBelievers;
86 }
87 private:
88 long itsNumberBelievers;
89 };
90
91 pegasus::pegasus(COLOR aColor,int height,bool migrates,long NumBelieve):horse(aColor,height),bird(aColor,migrates),itsNumberBeli
evers(NumBelieve)
92 {
93 cout << "pegasus constructor ...n";
94 }
95
96 int main()
97 {
98 pegasus *pPeg = new pegasus(red,5,true,10);
99 pPeg->fly();
100 pPeg->whinny();
101 cout << "n+++++++++ " << pPeg->getheight();
102 if(pPeg->getmigration())
103 cout << "[1]###n";
104 else
105 cout << "[2]###n";
106 cout << "n~~~~~ " << pPeg->getnumberbelievers();
107 delete pPeg;
108 return 0;
109 }
结果:
Horse constructor ...
bird constructor ...
pegasus constructor ...
i can fly!~~~~~~~~~~~~~~~~~
whinny!...

+++++++++ 5[1]###

~~~~~ 10pegasus destructor ...
bird destrutor ...
horse destructor ...

歧义解析:
如果在main中查看getcolor函数获得颜色,要注意两个基类都有颜色
cout << pPeg->getcolor() horse::getcolor() <

从共享基类中继承
例子:
1 #include
2 using namespace std;
3
4 enum COLOR {red,green,blue,yellow,white,black,brown};
5
6 class animal
7 {
8 public:
9 animal(int);
10 virtual ~animal()
11 {
12 cout << "animal desn";
13 }
14 virtual int getage() const
15 {
16 return itsage;
17 }
18 virtual void setage(int age)
19 {
20 itsage = age;
21 }
22 private:
23 int itsage;
24 };
25
26 animal::animal(int age):itsage(age)
27 {
28 cout << "animal conn";
29 }
30
31 class horse:public animal
32 {
33 public:
34 horse(COLOR color,int height,int age);
35 virtual ~horse()
36 {
37 cout << "horse desn";
38 }
39 virtual void whinny() const
40 {
41 cout << "whinny!n";
42 }
43 virtual int getheight() const
44 {
45 return itsHeight;
46 }
47 virtual COLOR getcolor() const
48 {
49 return itsColor;
50 }
51 protected:
52 int itsHeight;
53 COLOR itsColor;
54 };
55
56 horse::horse(COLOR color,int height, int age):animal(age),itsColor(color),itsHeight(height)
57 {
58 cout << "horse conn";
59 }
60
61 class bird:public animal
62 {
63 public:
64 bird(COLOR color,bool migrates,int age);
65 virtual ~bird()
66 {
67 cout << "bird desn";
68 }
69 virtual void chirp() const
70 {
71 cout << "chirp!n";
72 }
73 virtual void fly() const
74 {
75 cout << "i can fly!n";
76 }
77 virtual COLOR getcolor() const
78 {
79 return itsColor;
80 }
81 virtual bool getmigration() const
82 {
83 return itsmigration;
84 }
85 protected:
86 COLOR itsColor;
87 bool itsmigration;
88 };
89
90 bird::bird(COLOR color,bool migrates,int age):animal(age),itsColor(color),itsmigration(migrates)
91 {
92 cout << "bird conn";
93 }
94
95 class pegasus:public horse,public bird
96 {
97 public:
98 void chirp() const
99 {
100 whinny();
101 }
102 pegasus(COLOR, int, bool, long, int);
103 virtual ~pegasus()
104 {
105 cout << "pegasus desn";
106 }
107 virtual long getnumberbelievers() const
108 {
109 return itsnumberbelievers;
110 }
111 virtual COLOR getcolor() const
112 {
113 return horse::itsColor;
114 }
115 virtual int getage() const
116 {
117 return bird::getage();
118 //return horse::getage();
119 }
120 private:
121 long itsnumberbelievers;
122 };
123
124 pegasus::pegasus(COLOR aColor,int height,bool migrates,long numbelieve,int age):horse(aColor,height,age),bird(aColor,migrates,ag
e),itsnumberbelievers(numbelieve)
125 {
126 cout << "pegasus conn";
127 }
128
129 int main()
130 {
131 pegasus *pPeg = new pegasus(yellow,5,true,10,3);
132 int age = pPeg->getage();
133 cout << "================" << age <134 delete pPeg;
135
136 return 0;
137 }
结果:
animal con
horse con
animal con
bird con
pegasus con
================3
pegasus des
bird des
animal des
horse des
animal des

虚继承
在上个例子中,不想使用共享基类的两个副本,而是只想有一个共享基类
例子:
1 #include
2 using namespace std;
3
4 enum COLOR {red,green,blue,yellow,white,black,brown};
5
6 class animal
7 {
8 public:
9 animal(int);
10 virtual ~animal()
11 {
12 cout << "animal desn";
13 }
14 virtual int getage() const
15 {
16 return itsage;
17 }
18 virtual void setage(int age)
19 {
20 itsage = age;
21 }
22 private:
23 int itsage;
24 };
25
26 animal::animal(int age):itsage(age)
27 {
28 cout << "animal conn";
29 }
30
31 class horse: virtual public animal
32 {
33 public:
34 horse(COLOR color,int height,int age);
35 virtual ~horse()
36 {
37 cout << "horse desn";
38 }
39 virtual void whinny() const
40 {
41 cout << "whinny!n";
42 }
43 virtual int getheight() const
44 {
45 return itsHeight;
46 }
47 virtual COLOR getcolor() const
48 {
49 return itsColor;
50 }
51 protected:
52 int itsHeight;
53 COLOR itsColor;
54 };
55
56 horse::horse(COLOR color,int height, int age):animal(age),itsColor(color),itsHeight(height)
57 {
58 cout << "horse conn";
59 }
60
61 class bird:virtual public animal
62 {
63 public:
64 bird(COLOR color,bool migrates,int age);
65 virtual ~bird()
66 {
67 cout << "bird desn";
68 }
69 virtual void chirp() const
70 {
71 cout << "chirp!n";
72 }
73 virtual void fly() const
74 {
75 cout << "i can fly!n";
76 }
77 virtual COLOR getcolor() const
78 {
79 return itsColor;
80 }
81 virtual bool getmigration() const
82 {
83 return itsmigration;
84 }
85 protected:
86 COLOR itsColor;
87 bool itsmigration;
88 };
89
90 bird::bird(COLOR color,bool migrates,int age):animal(age),itsColor(color),itsmigration(migrates)
91 {
92 cout << "bird conn";
93 }
94
95 class pegasus:public horse,public bird
96 {
97 public:
98 void chirp() const
99 {
100 whinny();
101 }
102 pegasus(COLOR, int, bool, long, int);
103 virtual ~pegasus()
104 {
105 cout << "pegasus desn";
106 }
107 virtual long getnumberbelievers() const
108 {
109 return itsnumberbelievers;
110 }
111 virtual COLOR getcolor() const
112 {
113 return horse::itsColor;
114 }
115 virtual int getage() const
116 {
117 return bird::getage();
118 //return horse::getage();
119 }
120 private:
121 long itsnumberbelievers;
122 };
123
124 pegasus::pegasus(COLOR aColor,int height,bool migrates,long numbelieve,int age):horse(aColor,height,age),bird(aColor,migrates,ag
e),animal(age*2),itsnumberbelievers(numbelieve)
125 {
126 cout << "pegasus conn";
127 }
128
129 int main()
130 {
131 pegasus *pPeg = new pegasus(yellow,5,true,10,3);
132 int age = pPeg->getage();
133 cout << "================" << age <134 delete pPeg;
135
136 return 0;
137 }

结果:
animal con
horse con
bird con
pegasus con
================6
pegasus des
bird des
horse des
animal des

抽象类型,例子:
1 #include
2 using namespace std;
3
4 class shape
5 {
6 public:
7 shape(){}
8 virtual ~shape(){}
9 virtual long getarea(){return -1;}
10 virtual long getperim(){return -1;}
11 virtual void draw(){}
12 private:
13 };
14
15 class circle:public shape
16 {
17 public:
18 circle(int radius):itsradius(radius){}
19 ~circle(){}
20 long getarea () {return 3*itsradius * itsradius;}
21 long getperim(){return 6*itsradius;}
22 void draw();
23 private:
24 int itsradius;
25 int itscircumference;
26 };
27
28 void circle::draw()
29 {
30 cout << "circle drawn";
31 }
32
33 class rectangle:public shape
34 {
35 public:
36 rectangle(int len, int width):itslength(len),itswidth(width) {}
37 virtual ~rectangle(){}
38 virtual long getarea(){return itslength*itswidth;}
39 virtual long getperim(){return 2*itslength + 2*itswidth;}
40 virtual int getlength(){return itslength;}
41 virtual int getwidth(){return itswidth;}
42 virtual void draw();
43 private:
44 int itswidth;
45 int itslength;
46 };
47
48 void rectangle::draw()
49 {
50 for(int i = 0; i < itslength; i++)
51 {
52 for(int j = 0; j < itswidth; j++)
53 cout << " x";
54 cout << "n";
55 }
56 }
57
58 class square:public rectangle
59 {
60 public:
61 square(int len);
62 square(int len, int width);
63 ~square(){}
64 long getperim()
65 {
66 return 4*getlength();
67 }
68 };
69
70 square::square(int len):rectangle(len,len)
71 {}
72
73 square::square(int len, int width):rectangle(len, width)
74 {
75 if(getlength() != getwidth())
76 cout << "error ^_^n";
77 }
78
79 int main()
80 {
81 int choice;
82 bool fquit = false;
83 shape *sp;
84
85 while(!fquit)
86 {
87 cout << "1:circle 2:rectangle 3:square 0:quit:";
88 cin >> choice;
89
90 switch(choice)
91 {
92 case 0:
93 fquit = true;
94 break;
95 case 1:
96 sp = new circle(5);
97 break;
98 case 2:
99 sp = new rectangle(4,6);
100 break;
101 case 3:
102 sp = new square(5);
103 break;
104 default:
105 cout << "please enter a number: ";
106 continue;
107 break;
108 }
109 if(!fquit)
110 sp->draw();
111 delete sp;
112 sp = 0;
113 cout << "n";
114 }
115 return 0;
116 }
结果:
1:circle 2:rectangle 3:square 0:quit:1
circle draw

1:circle 2:rectangle 3:square 0:quit:2
x x x x x x
x x x x x x
x x x x x x
x x x x x x

1:circle 2:rectangle 3:square 0:quit:3
x x x x x
x x x x x
x x x x x
x x x x x
x x x x x

1:circle 2:rectangle 3:square 0:quit:4
please enter a number: 1:circle 2:rectangle 3:square 0:quit:0

纯虚函数
一个虚函数初始化为0编程了纯虚函数
virtual void Draw()=0;
把一个纯虚函数放在你的类中对你的类的客户来说意味着两件事:
1:不要从这个类中创建对象,要从其中派生
2:确信覆盖了纯虚函数。
上面的程序
将shape改写
class shape
{
public:
shape(){}
~shape(){}
virtual long getarea() = 0;
virtual long getperim() = 0;
virtual void draw() = 0;
private:
};
重新运行程序,程序运行不受影响,唯一区别是现在不能创建一个shape类的对象。

实现纯虚函数,只要其中任何一个被声明为纯虚函数,那么这个类就是一个ADT
例子:
1 #include
2 using namespace std;
3
4 class shape
5 {
6 public:
7 shape(){}
8 virtual ~shape(){}
9
10 virtual long getarea() = 0;
11 virtual long getperim() = 0;
12 virtual void draw() = 0;
13 private:
14 };
15
16 void shape::draw()
17 {
18 cout << "abstract drawing !!!!!!!!!!!!!!n";
19 }
20
21 class circle:public shape
22 {
23 public:
24 circle(int radius):itsradius(radius){}
25 virtual ~circle(){}
26 long getarea () {return 3*itsradius * itsradius;}
27 long getperim(){return 9*itsradius;}
28 void draw();
29 private:
30 int itsradius;
31 int itscircumference;
32 };
33
34 void circle::draw()
35 {
36 cout << "circle drawn";
37 shape::draw();
38 }
39
40 class rectangle:public shape
41 {
42 public:
43 rectangle(int len, int width):itslength(len),itswidth(width) {}
44 virtual ~rectangle(){}
45 long getarea(){return itslength*itswidth;}
46 long getperim(){return 2*itslength + 2*itswidth;}
47 virtual int getlength(){return itslength;}
48 virtual int getwidth(){return itswidth;}
49 void draw();
50 private:
51 int itswidth;
52 int itslength;
53 };
54
55 void rectangle::draw()
56 {
57 for(int i = 0; i < itslength; i++)
58 {
59 for(int j = 0; j < itswidth; j++)
60 cout << " x";
61 cout << "n";
62 }
63 shape::draw();
64 }
65
66 class square:public rectangle
67 {
68 public:
69 square(int len);
70 square(int len, int width);
71 virtual ~square(){}
72 long getperim()
73 {
74 return 4*getlength();
75 }
76 };
77
78 square::square(int len):rectangle(len,len)
79 {}
80
81 square::square(int len, int width):rectangle(len, width)
82 {
83 if(getlength() != getwidth())
84 cout << "error ^_^n";
85 }
86
87 int main()
88 {
89 int choice;
90 bool fquit = false;
91 shape *sp;
92
93 while(!fquit)
94 {
95 cout << "1:circle 2:rectangle 3:square 0:quit:";
96 cin >> choice;
97
98 switch(choice)
99 {
100 case 0:
101 fquit = true;
102 break;
103 case 1:
104 sp = new circle(5);
105 break;
106 case 2:
107 sp = new rectangle(4,6);
108 break;
109 case 3:
110 sp = new square(5);
111 break;
112 default:
113 cout << "please enter a number: ";
114 continue;
115 break;
116 }
117 if(!fquit)
118 sp->draw();
119 delete sp;
120 sp = 0;
121 cout << "n";
122 }
123 return 0;
124 }
结果:
1:circle 2:rectangle 3:square 0:quit:1
circle draw
abstract drawing !!!!!!!!!!!!!!

1:circle 2:rectangle 3:square 0:quit:2
x x x x x x
x x x x x x
x x x x x x
x x x x x x
abstract drawing !!!!!!!!!!!!!!

1:circle 2:rectangle 3:square 0:quit:3
x x x x x
x x x x x
x x x x x
x x x x x
x x x x x
abstract drawing !!!!!!!!!!!!!!

1:circle 2:rectangle 3:square 0:quit:4
please enter a number: 1:circle 2:rectangle 3:square 0:quit:0

circle和rectangle都覆盖了draw(),两者都是链接到了基方法,利用了基类中的共享功能。

从其他的ADT中派生ADT
例子:
1 #include
2 using namespace std;
3
4 enum COLOR {red,green,blue,yellow,white,black,brown};
5
6 class animal
7 {
8 public:
9 animal(int);
10 virtual ~animal(){cout << "animal desn";}
11 virtual int getage() const {return itsage;}
12 virtual void setage(int age){itsage = age;}
13
14 virtual void sleep() const = 0;
15 virtual void eat() const = 0;
16 virtual void reproduce() const = 0;
17 virtual void move() const = 0;
18 virtual void speak() const = 0;
19 private:
20 int itsage;
21 };
22
23 animal::animal(int age):itsage(age)
24 {
25 cout << "animal conn";
26 }
27
28 class mammal:public animal
29 {
30 public:
31 mammal(int age):animal(age)
32 {
33 cout << "Mammal conn";
34 }
35 virtual ~mammal()
36 {
37 cout << "Mammal desn";
38 }
39 virtual void reproduce() const
40 {
41 cout << "Mammal reproductionn";
42 }
43 };
44
45 class fish:public animal
46 {
47 public:
48 fish(int age):animal(age)
49 {
50 cout << "fish conn";
51 }
52 virtual ~fish()
53 {
54 cout << "fish desn";
55 }
56 virtual void sleep() const
57 {
58 cout << "fish snoringn";
59 }
60 virtual void eat() const
61 {
62 cout << "fish feedingn";
63 }
64 virtual void reproduce() const
65 {
66 cout << "fish laying eggsn";
67 }
68 virtual void move() const
69 {
70 cout << "fish swimmingn";
71 }
72 virtual void speak() const
73 {
74 }
75 };
76
77 class horse:public mammal
78 {
79 public:
80 horse(int age,COLOR color):mammal(age),itscolor(color)
81 {
82 cout << "horse conn";
83 }
84 virtual ~horse()
85 {
86 cout << "horse desn";
87 }
88 virtual void speak() const
89 {
90 cout << "horse speak";
91 }
92 virtual COLOR getitscolor()const
93 {
94 return itscolor;
95 }
96 virtual void sleep()const
97 {
98 cout << "horse sleepn";
99 }
100 virtual void eat() const
101 {
102 cout << "horse eatn";
103 }
104 virtual void move() const
105 {
106 cout << "horse moven";
107 }
108 protected:
109 COLOR itscolor;
110 };
111
112 class dog:public mammal
113 {
114 public:
115 dog(int age, COLOR color):mammal(age),itscolor(color)
116 {
117 cout << "dog conn";
118 }
119 virtual ~dog(){cout << "dog desn";}
120 virtual void speak() const
121 {
122 cout << "dog speakn";
123 }
124 virtual void sleep() const
125 {
126 cout << "dog sleepn";
127 }
128 virtual void eat() const
129 {
130 cout << "dog eatn";
131 }
132 virtual void move() const
133 {
134 cout << "dog moven";
135 }
136 virtual void reproduce() const
137 {
138 cout << "dog reproducen";
139 }
140 protected:
141 COLOR itscolor;
142 };
143
144 int main()
145 {
146 animal *panimal=0;
147 int choice;
148 bool fquit=false;
149
150 while(1)
151 {
152 cout << "1: dog 2:horse 3:fish 0:quit :";
153 cin >> choice;
154
155 switch (choice)
156 {
157 case 1:
158 panimal = new dog(5,brown);
159 break;
160 case 2:
161 panimal = new horse(4,black);
162 break;
163 case 3:
164 panimal = new fish(5);
165 break;
166 default:
167 fquit = true;
168 break;
169 }
170 if(fquit)
171 break;
172
173 panimal->speak();
174 panimal->eat();
175 panimal->reproduce();
176 panimal->move();
177 panimal->sleep();
178
179 delete panimal;
180
181 cout << "n";
182 }
183 return 0;
184 }
185
结果:
1: dog 2:horse 3:fish 0:quit :1
animal con
Mammal con
dog con
dog speak
dog eat
dog reproduce
dog move
dog sleep
dog des
Mammal des
animal des

1: dog 2:horse 3:fish 0:quit :2
animal con
Mammal con
horse con
horse speakhorse eat
Mammal reproduction
horse move
horse sleep
horse des
Mammal des
animal des

1: dog 2:horse 3:fish 0:quit :3
animal con
fish con
fish feeding
fish laying eggs
fish swimming
fish snoring
fish des
animal des

1: dog 2:horse 3:fish 0:quit :4

mammal从animal派生,但覆盖了reproduce()方法,为所有哺乳动物提供了相同的繁殖方式,fish必须覆盖reproduce(),因为它是直接从animal类中派生的,不能利用哺乳动物的繁殖方式。mammal类不再必须覆盖reproduce()方法。fish、horse和dog均覆盖了剩余的纯虚函数,这样他们那一类型的对象就可以实例化了,试图实例化animal和mammal会产生编译错误,因为他们都是抽象数据类型。

静态成员变量
静态成员变量在一个类的所有对象中是共享的。可以把静态成员变量看作属于类的而不是属于对象的。
1 #include
2
3 using namespace std;
4
5 class cat
6 {
7 public:
8 cat(int age):itsage(age)
9 {
10 howmanycats++;
11 }
12 virtual ~cat()
13 {
14 howmanycats--;
15 }
16 virtual int getage()
17 {
18 return itsage;
19 }
20 virtual void setage(int age)
21 {
22 itsage = age;
23 }
24 static int howmanycats;
25 private:
26 int itsage;
27 };
28
29 int cat::howmanycats = 0;
30
31 int main()
32 {
33 const int maxcats = 5;
34 int i;
35 cat *cathouse[maxcats];
36
37 for(i = 0; i < maxcats; i++)
38 cathouse[i] = new cat(i);
39
40 for(i = 0; i < maxcats; i++)
41 {
42 cout << cat::howmanycats << endl;
43 cout << cathouse[i]->getage() << endl;
44
45 delete cathouse[i];
46 cathouse[i] = 0;
47 }
48 return 0;
49 }
结果:
5
0
4
1
3
2
2
3
1
4

永远通过一个cat实例来访问这些数据,那么最好是这个成员变量和其他成员变量一起成为私有变量,并且提供一个公有访问函数。另一方面,如果你想在不必使用cat对象的情况下直接访问这个数据,可以有两种方法:把它变成公有变量,或提供一个静态成员函数。

访问没有对象的静态成员
例子:
1 #include
2
3 using namespace std;
4
5 class cat
6 {
7 public:
8 cat(int age):itsage(age)
9 {
10 howmanycats++;
11 }
12 virtual ~cat()
13 {
14 howmanycats--;
15 }
16 virtual int getage()
17 {
18 return itsage;
19 }
20 virtual void setage(int age)
21 {
22 itsage = age;
23 }
24 static int howmanycats;
25 private:
26 int itsage;
27 };
28
29 int cat::howmanycats = 0;
30
31 void fun();
32
33 int main()
34 {
35 const int maxcats = 3;
36 int i;
37 cat *cathouse[maxcats];
38
39 for(i = 0; i < maxcats; i++)
40 {
41 cathouse[i] = new cat(i);
42 fun();
43 }
44
45 for(i = 0; i < maxcats; i++)
46 {
47 delete cathouse[i];
48 fun();
49 }
50 return 0;
51 }
52
53 void fun()
54 {
55 cout << cat::howmanycats << endl;
56 }
结果:
1
2
3
2
1
0

用非静态成员函数访问静态成员
例子:
1 #include
2
3 using namespace std;
4
5 class cat
6 {
7 public:
8 cat(int age):itsage(age)
9 {
10 howmanycats++;
11 }
12 virtual ~cat()
13 {
14 howmanycats--;
15 }
16 virtual int getage()
17 {
18 return itsage;
19 }
20 virtual void setage(int age)
21 {
22 itsage = age;
23 }
24 virtual int gethowmany()
25 {
26 return howmanycats;
27 }
28 private:
29 static int howmanycats;
30 int itsage;
31 };
32
33 int cat::howmanycats = 0;
34
35 int main()
36 {
37 const int maxcats = 3;
38 int i;
39 cat *cathouse[maxcats];
40
41 for(i = 0; i < maxcats; i++)
42 {
43 cathouse[i] = new cat(i);
44 }
45
46 for(i = 0; i < maxcats; i++)
47 {
48 cout << cathouse[i]->gethowmany() << endl;
49 delete cathouse[i];
50 cathouse[i] = 0;
51 }
52 return 0;
53 }
结果:
3
2
1

必须用静态成员变量来在一个类的所有实例间共享数据。如果相对静态成员变量的访问,则必须把他们声明为保护型或私有型。不应该用静态成员变量去存放某一个对象的数据,静态成员数据是在这个类的所有对象间共享的。

静态成员函数
例子:
1 #include
2
3 using namespace std;
4
5 class cat
6 {
7 public:
8 cat(int age):itsage(age)
9 {
10 howmanycats++;
11 }
12 virtual ~cat()
13 {
14 howmanycats--;
15 }
16 virtual int getage()
17 {
18 return itsage;
19 }
20 virtual void setage(int age)
21 {
22 itsage = age;
23 }
24 static int gethowmany()
25 {
26 return howmanycats;
27 }
28 private:
29 int itsage;
30 static int howmanycats;//声明为私有访问
31 };
32
33 int cat::howmanycats = 0;
34
35 void tel();
36
37 int main()
38 {
39 const int max = 5;
40 cat *cathouse[max];
41 int i;
42 for(i = 0; i < max; i++)
43 {
44 cathouse[i] = new cat(i);
45 tel();
46 }
47
48 for(i = 0; i < max; i++)
49 {
50 delete cathouse[i];
51 tel();
52 }
53 return 0;
54 }
55
56 void tel()
57 {
58 cout << cat::gethowmany() << endl;
59 }
结果:
1
2
3
4
5
4
3
2
1
0
由于gethowmany()是公有的,因此它可以由任何一个函数访问,又由于它是静态的,因此不必有一个cat型对象来调用它。
静态成员函数没有this指针,因此他们不能声明为const。还由于成员数据变量在成员函数内是通过this指针来访问的,因此静态成员函数不能访问任何非静态成员变量!
就像调用其他成员函数一样,你可以通过在这个类的某个对象中调用静态成员函数来访问静态成员函数。或者你可不必采用完全限定类和对象名的对象来调用静态成员函数。

函数指针
例子
1 #include
2 using namespace std;
3
4 void square(int&,int&);
5 void cube(int&,int&);
6 void swap(int&,int&);
7 void getvals(int&,int&);
8 void printvals(int,int);
9
10 int main()
11 {
12 void (* pfunc)(int&,int&);
13 bool fquit = false;
14
15 int valone = 1, valtwo = 2;
16 int choice;
17
18 while(fquit == false)
19 {
20 cout << "0:quit 1:change values 2:square 3:cube 4:swap: ";
21 cin >> choice;
22 switch(choice)
23 {
24 case 1: pfunc = getvals; break;
25 case 2: pfunc = square; break;
26 case 3: pfunc = cube; break;
27 case 4: pfunc = swap; break;
28 default: fquit = true; break;
29 }
30
31 if(fquit)
32 break;
33
34 printvals(valone,valtwo);
35 pfunc(valone,valtwo);
36 printvals(valone,valtwo);
37 }
38 return 0;
39 }
40
41 void printvals(int x, int y)
42 {
43 cout << "x: " << x << "y: " << y << endl;
44 }
45
46 void square(int& rx, int& ry)
47 {
48 rx *= rx;
49 ry *= ry;
50 }
51
52 void cube(int& rx, int& ry)
53 {
54 int tmp;
55 tmp = rx;
56 rx *= rx;
57 rx = rx*tmp;
58
59 tmp = ry;
60 ry *= ry;
61 ry = ry*tmp;
62 }
63
64 void swap(int& rx, int& ry)
65 {
66 int tmp;
67 tmp = rx;
68 rx = ry;
69 ry = tmp;
70 }
71
72 void getvals(int& rx, int& ry)
73 {
74 cout << "new value for valone:";
75 cin >> rx;
76 cout << "new value for valtwo:";
77 cin >> ry;
78
79 }
结果:
0:quit 1:change values 2:square 3:cube 4:swap: 1
x: 1y: 2
new value for valone:5
new value for valtwo:6
x: 5y: 6
0:quit 1:change values 2:square 3:cube 4:swap: 2
x: 5y: 6
x: 25y: 36
0:quit 1:change values 2:square 3:cube 4:swap: 3
x: 25y: 36
x: 15625y: 46656
0:quit 1:change values 2:square 3:cube 4:swap: 4
x: 15625y: 46656
x: 46656y: 15625
0:quit 1:change values 2:square 3:cube 4:swap: 0

pFunc(x) <=> (* pFunc)(x) 前一种是后一种的简化形式

函数指针数组
例子:
1 #include
2 using na

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/23168012/viewspace-1047132/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/23168012/viewspace-1047132/

你可能感兴趣的:(21天学通C++(第四版)笔记)