一.类成员函数的定义方法

1.在类声明中声明,类声明外定义

 1 #include<iostream>
 2 using namespace std;
 3 
 4 class Person
 5 {
 6 public:
 7     void setAge(unsigned n);
 8     unsigned getAge() const;
 9 private:
10     unsigned age;
11 };
12 
13 void Person::setAge(unsigned n)
14 {
15     age = n;
16 }
17 
18 unsigned Person::getAge() const
19 {
20     return age;
21 }
22 
23 int main()
24 {
25     return 0;
26 }

2.在类声明中声明和定义

 1 #include<iostream>
 2 using namespace std;
 3 
 4 class Person
 5 {
 6 public:
 7     void setAge(unsigned n)
 8     {
 9         age = n;
10     }
11 
12     unsigned getAge() const
13     {
14         return age;
15     }
16 private:
17     unsigned age;
18 };
19 
20 int main()
21 {
22     return 0;
23 }

二.类声明通常放到.h文件中,不要将成员函数的定义放到.h中

三.一般来说应该采用引用的方式进行对象的传递和返回,而不要采用传值。传递一个指向对象的指针和引用方式效果相同,但引用语法简练。

四.const用法

const成员函数仅能调用其它const成员函数,非const成员函数可能会间接地改变对象状态

1.重载,2个成员函数(函数名,参数列表)一致,但一个有const一个无

不算重名,算重载

常对象调用常函数,非常对象调用非常函数

 1 #include<iostream>
 2 using namespace std;
 3 
 4 class A
 5 {
 6 public:
 7     A()
 8     {
 9         x = 5;
10     }
11     int getValue()
12     {
13         return x;
14     }
15 
16     int getValue() const
17     {
18         return 2 * x;
19     }
20 private:
21     unsigned x;
22 };
23 
24 int main()
25 {
26     A a1;
27     const A a2;
28     cout << a1.getValue() << endl; // 5
29     cout << a2.getValue() << endl; // 10
30     return 0;
31 }

2.三种const

 1 #include<iostream>
 2 using namespace std;
 3 
 4 class C
 5 {
 6 public:
 7     void set(const int n)//set不会改变n
 8     {
 9         x = n;
10     }
11 
12     const int& get() const//第一个const:get会返回一个const型引用,谁也不能通过这个引用修改x,不能修改返回值
13     {                     //第二个const:get不会改变C中的数据成员
14         return x;
15     }
16 private:
17     int x
18 };
19 
20 int main()
21 {
22     return 0;
23 }

若函数采用const返回,则返回值只赋给一个const类型局部变量;

const返回值是一个类的指针或者引用的话,则不能用该指针或者引用调用该类的non-const成员函数,因为这些函数可能会改变该类数据成员;

常量对象不能执行非常量成员函数。

 1 #include<iostream>
 2 using namespace std;
 3 
 4 class C
 5 {
 6 public:
 7     int &f1()
 8     {
 9         mszt = 5;
10         return mszt; // 可修改mstz,可修改返回值
11     }
12 
13     int &f2() const
14     {
15         return a; // error,无法将const int转换为int&,去掉&
16     }
17 
18     const int& f3()
19     {
20         a = 5;
21         return a; //可修改a,不可修改返回值
22     }
23 
24     void PrintMszt()
25     {
26         cout << mszt << endl;
27     }
28 
29     void PrintA()
30     {
31         cout << a << endl;
32     }
33 private:
34     int mszt, a;
35 };
36 
37 int main()
38 {
39     C c;
40     int &s = c.f3(); // error,s不是const
41     const int& s1 = c.f3(); //ok
42     cout << s1 << endl;
43     s1 = 20;//error
44     return 0;
45 }

3.对const成员不能直接赋值

 1 #include <iostream>
 2 #include <string>
 3 using namespace std;
 4 
 5 class C
 6 {
 7 public:
 8     C():c(0)//要用初始化列表
 9     {
10         x = -1;
11     }
12 
13 private:
14     const int c;
15     int x;
16 };
17 
18 int main()
19 {
20     return 0;
21 }

五.构造函数

1.构造函数无返回类型,与类同名;

2.创建一个对象时,构造函数会被编译器自动调用;

3.希望只使用带参构造函数时,提供公有带参构造函数,而不提供默认构造函数,或者提供私有的默认构造函数

 1 #include<iostream>
 2 using namespace std;
 3 
 4 class C
 5 {
 6 public:
 7     C(int a) {}
 8 private:
 9     C() {}
10 };
11 
12 int main()
13 {
14     C c;//error
15     C c(1);//OK
16     return 0;
17 }

六.拷贝构造

Person(Person&); Person(const Person&);

拷贝构造函数可以有多于一个的参数,但第一个以后的所有参数都必须有默认值

Person(const Person& p, bool married = false);

若一个类包含指向动态存储空间指针类型的数据成员,应为这个类设计拷构。否则:

 1 #include<iostream>
 2 using namespace std;
 3 
 4 class P
 5 {
 6 public:
 7     P();
 8     P(const string[], int);
 9     void set(const string[], int);
10 private:
11     int size;
12     string *p;
13 };
14 
15 int main()
16 {
17     string list[10];
18     P p1(list, 3);
19     P p2(p1);//默认拷构
20     return 0;
21 }

p1.p和p2.p指向同一块存储空间,潜在p1的操作会改变p2,且调用析构时会对同一值析构两次。

 1 #include<iostream>
 2 using namespace std;
 3 
 4 class C
 5 {
 6 public:
 7     C()
 8     {
 9         cout << "Default" << endl;
10         num = 0;
11     }
12 
13     C(const C &c)
14     {
15         cout << "Copy" << endl;
16         //num = c.num;若有,若无
17     }
18 
19     void set(int n)
20     {
21         num = n;
22     }
23 
24     int get() const
25     {
26         return num;
27     }
28 private:
29     int num;
30 };
31 
32 void f(C c4)//copy
33 {
34     cout << "enter f(c)" << '	';
35     c4.set(-999);
36     cout << "c4:" << c4.get() << '	' << "leaving f(c)" << endl;
37 }
38 
39 C g()
40 {
41     cout << "enter g()" << endl;
42     C c3;//default
43     cout << "c3:" << c3.get() << '
';
44     c3.set(123);
45     cout << "c3:" << c3.get() << '	' << "leaving g()" << endl;
46     return c3;//copy
47 }
48 
49 int main()
50 {
51     C c1, c2;//default
52     cout << "c1:" << c1.get() << '	';
53     cout << "c2:" << c2.get() << endl;
54     f(c1);
55     cout << "c1:" << c1.get() << endl;
56     c2 = g();
57     cout << "c2:" << c2.get() << endl;//若有123,若无乱码
58     return 0;
59 }

用一个已存在的对象去构造一个不存在的对象(构造之前不存在)就是拷贝构造。用一个已存在的对象去覆盖另一个已存在的对象,就是赋值运算。

若对象很大,进行对象间的拷贝的话,非常费空间和时间,改进:

      把拷贝构造设计成私有成员;

      把void f(C c)=> void f(C &c),C g()=>C &g()

七.转型构造函数(单参数构造函数)

 1 #include<iostream>
 2 using namespace std;
 3 
 4 class Complex
 5 {
 6 public:
 7     Complex(int i)
 8     {
 9         cout << "Int Constructor" << endl;
10         real = i, imag = 0;
11     }
12 
13     Complex(double r, double i)
14     {
15         cout << "Double Constructor" << endl;
16         real = r, imag = i;
17     }
18 
19     Complex(Complex &c)
20     {
21         cout << "Copy Constructor" << endl;
22         real = c.real;
23         imag = c.imag;
24     }
25 
26     int real, imag;
27 };
28 
29 int main()
30 {
31     Complex c1(7, 8);//Double Constructor
32     Complex c2 = 12;//Int Constructor
33     c1 = 9;//Int Constructor, 9隐式类型转换
34     cout << c1.real << " " << c2.imag << endl;//9 0
35     Complex c3 = c1;//Copy Constructor
36     return 0;
37 }
 1 #include <iostream>
 2 #include <string>
 3 using namespace std;
 4 
 5 class Person
 6 {
 7 public:
 8     Person()
 9     {
10         name = "Unknown";
11     }
12 
13     Person(const string &n)//转型构造
14     {
15         cout << "转型" << endl;
16         name = n;
17     }
18 
19     Person(const char *n)//转型构造
20     {
21         cout << "转型" << endl;
22         name = n;
23     }
24 
25     Person(Person &p)//转型构造
26     {
27         cout << "Copy" << endl;
28         name = p.name;
29     }
30 
31     string name;
32 };
33 
34 void f(Person p)
35 {
36     cout << 1 << endl;
37 }
38 
39 int main()
40 {
41     Person s1("Dave");
42     Person s2("Ben");
43     string str = "Peter";
44     f(str);//显示“转型”,不显示“转型”,在构造时,调用了转型构造函数
45     s1 = str;//str转型为Person类型,显示“转型”
46     s1 = s2;//什么都不显示,不存在Copy和转型
47     return 0;
48 }
 1 #include <iostream>
 2 #include <string>
 3 using namespace std;
 4 
 5 class Person
 6 {
 7 public:
 8     Person()
 9     {
10         name = "Unknown";
11     }
12 
13     explicit Person(const string &n)//在转型构造函数前加上explicit,关闭隐式类型转换
14     {
15         name = n;
16     }
17 private:
18     string name;
19 };
20 
21 int main()
22 {
23     Person p("Dave");
24     string b = "bar";
25     p = b;//error
26     return 0;
27 }

 

八.析构函数

析构函数没有参数和返回值,一个类最多一个析构函数

定义类时没写析构函数,则编译器生成缺省析构函数,不涉及释放用户申请的内存释放等清理工作。

 1 #include<iostream>
 2 using namespace std;
 3 
 4 class C
 5 {
 6 public:
 7     C()
 8     {
 9         cout << "Construct" << endl;
10     }
11     ~C()
12     {
13         cout << "Destructor" << endl;
14     }
15 };
16 
17 int main()
18 {
19     C c1[2], *c2 = new C[3];
20     return 0;
21 }
22 /*
23 Construct
24 Construct
25 Construct
26 Construct
27 Construct
28 Destructor
29 Destructor
30 */
 1 #include<iostream>
 2 using namespace std;
 3 
 4 class C
 5 {
 6 public:
 7     C()
 8     {
 9         cout << "Construct" << endl;
10     }
11     ~C()
12     {
13         cout << "Destructor" << endl;
14     }
15 };
16 
17 int main()
18 {
19     C *c2 = new C[3];
20     delete[] c2;
21     return 0;
22 }
23 /*
24 Construct
25 Construct
26 Construct
27 Destructor
28 Destructor
29 Destructor
30 */
原文地址:https://www.cnblogs.com/wanderingzj/p/5294784.html