本文学习自 狄泰软件学院 唐佐林老师的 C++课程
实验1:构造与析构的顺序
实验2:只读对象的成员变量是只读变量
实验3:只读对象只能调用const成员函数。
实验4:const 成员函数内部不能直接修改成员变量的值,并且函数内部只能调用const 成员函数
实验5: this 当前对象指针
实验6 :在非const 成员函数中,可以直接访问修改所有的成员变量,也可以通过对象名访问所有的成员变量
实验1:构造与析构的顺序
#include <stdio.h>
class Member
{
const char* ms;
public:
Member(const char* s)
{
printf("Member(const char* s): %s\n", s);
ms = s;
}
~Member()
{
printf("~Member(): %s\n", ms);
}
};
class Test
{
Member mA;
Member mB;
public:
Test() : mB("mB"), mA("mA")
{
printf("Test()\n");
}
~Test()
{
printf("~Test()\n");
}
};
Member gA("gA");
int main()
{
Test t;
return 0;
}
mhr@ubuntu:~/work/c++$
mhr@ubuntu:~/work/c++$ g++ 24-1.cpp
mhr@ubuntu:~/work/c++$ ./a.out
Member(const char* s): gA
Member(const char* s): mA
Member(const char* s): mB
Test()
~Test()
~Member(): mB
~Member(): mA
~Member(): gA
mhr@ubuntu:~/work/c++$
实验2:只读对象的成员变量是只读变量
#include <stdio.h>
class Test
{
int mi;
public:
int mj;
Test(int i);
Test(const Test& t);
int getMi();
};
Test::Test(int i)
{
mi = i;
}
Test::Test(const Test& t)
{
}
int Test::getMi()
{
return mi;
}
int main()
{
const Test t(1);
j.mj=100;
return 0;
}
mhr@ubuntu:~/work/c++$ g++ 24-2.cpp
24-2.cpp: In function ‘int main()’:
24-2.cpp:31:10: error: assignment of member ‘Test::mj’ in read-only object
t.mj = 100;
^
mhr@ubuntu:~/work/c++$
实验3:只读对象只能调用const成员函数
#include <stdio.h>
class Test
{
int mi;
public:
int mj;
Test(int i);
Test(const Test& t);
int getMi();
};
Test::Test(int i)
{
mi = i;
}
Test::Test(const Test& t)
{
}
int Test::getMi()
{
return mi;
}
int main()
{
const Test t(1);
printf("t.getMi() = %d\n", t.getMi());
return 0;
}
mhr@ubuntu:~/work/c++$ g++ 24-2.cpp
24-2.cpp: In function ‘int main()’:
24-2.cpp:31:40: error: passing ‘const Test’ as ‘this’ argument discards qualifiers [-fpermissive]
printf("t.getMi() = %d\n", t.getMi());
^
24-2.cpp:23:5: note: in call to ‘int Test::getMi()’
int Test::getMi()
^
mhr@ubuntu:~/work/c++$
提示只读对象不能调用非const的成员函数。
修改:为成员函数添加 const属性
#include <stdio.h>
class Test
{
int mi;
public:
int mj;
Test(int i);
Test(const Test& t);
int getMi()const;
};
Test::Test(int i)
{
mi = i;
}
Test::Test(const Test& t)
{
}
int Test::getMi()const
{
return mi;
}
int main()
{
const Test t(1);
printf("t.getMi() = %d\n", t.getMi());
return 0;
}
mhr@ubuntu:~/work/c++$ g++ 24-2.cpp
mhr@ubuntu:~/work/c++$ ./a.out
t.getMi() = 1
mhr@ubuntu:~/work/c++$
实验4; const 成员函数内部不能直接修改成员变量的值,并且函数内部只能调用const 成员函数
#include <stdio.h>
class Test
{
int mi;
public:
int mj;
Test(int i);
Test(const Test& t);
int getMi()const;
};
Test::Test(int i)
{
mi = i;
}
Test::Test(const Test& t)
{
}
int Test::getMi()const
{
mi = 2;
return mi;
}
int main()
{
const Test t(1);
printf("t.getMi() = %d\n", t.getMi());
return 0;
}
mhr@ubuntu:~/work/c++$
mhr@ubuntu:~/work/c++$ g++ 24-2.cpp
24-2.cpp: In member function ‘int Test::getMi() const’:
24-2.cpp:25:8: error: assignment of member ‘Test::mi’ in read-only object
mi = 2;
^
mhr@ubuntu:~/work/c++$
const 成员函数内部不能直接修改成员变量的值,并且函数内部只能调用const 成员函数
改:
#include <stdio.h>
class Test
{
int mi;
public:
int mj;
Test(int i);
Test(const Test& t);
int getMi()const;
};
Test::Test(int i)
{
mi = i;
}
//拷贝构造函数参数是 const 引用,t是只读对象,只能调用const 成员函数
Test::Test(const Test& t)
{
mi = t.getMi();
}
int Test::getMi()const
{
return mi;
}
int main()
{
const Test t(1);
return 0;
}
所有的对象共用一套成员函数,因为从程序运行的角度来看,对象是由数据和函数所构成的,数据只可能位于栈,堆或者全局数据区中,而函数只能位于代码段,而代码段是只读的,在程序运行的时候是不可以改变的,当编译器将最终的可执行程序编译好之后,代码段就被确定了,不可以被改动。而我们的对象是可以动态的被创建,动态的删除,对于数据而言,当然可以做到动态的创建和删除,然而对于函数即代码段而言,是不可能的,也就是说在面向对象中,由于程序的特性,成员函数是不可能每个对象都有自己的一套的,只有是所有的对象共享一套成员函数,原因很简单,就是代码段是不能动态的添加和删除的。
问题:如果所有的对象都共享一套成员函数,那各个成员函数本身被调用的时候是怎么分辨是哪个对象调用自己的呢?
实验5: this 当前对象指针
#include <stdio.h>
class Test
{
int mi;
public:
int mj;
Test(int i);
Test(const Test& t);
int getMi();
void print();
};
Test::Test(int i)
{
mi = i;
}
Test::Test(const Test& t)
{
mi = t.mi;
}
int Test::getMi()
{
return mi;
}
void Test::print()
{
printf("this = %p\n", this);
}
int main()
{
Test t1(1);
Test t2(2);
Test t3(3);
printf("t1.getMi() = %d\n", t1.getMi());
printf("&t1 = %p\n", &t1);
t1.print();
printf("t2.getMi() = %d\n", t2.getMi());
printf("&t2 = %p\n", &t2);
t2.print();
printf("t3.getMi() = %d\n", t3.getMi());
printf("&t3 = %p\n", &t3);
t3.print();
return 0;
}
mhr@ubuntu:~/work/c++$ g++ 24-3.cpp
mhr@ubuntu:~/work/c++$ ./a.out
t1.getMi() = 1
&t1 = 0x7ffd6d1dc1b0
this = 0x7ffd6d1dc1b0
t2.getMi() = 2
&t2 = 0x7ffd6d1dc1c0
this = 0x7ffd6d1dc1c0
t3.getMi() = 3
&t3 = 0x7ffd6d1dc1d0
this = 0x7ffd6d1dc1d0
mhr@ubuntu:~/work/c++$
结论:在类的成员函数中,有一个隐含的成员参数 this指针,这个指针的值就是调用这个成员函数的对象的地址,this 指针在成员函数中,表示指向当前调用这个函数的对象地址,也就是说this指向当前对象。
成员函数与普通函数是不一样的,成员函数拥有一个隐含的this指针,用于指向当前对象地址。
实验6 :成员函数中可以直接访问对象的成员变量,哪怕是通过对象 和’.'操作符来访问私有成员变量 都是合法的
#include <stdio.h>
class Test
{
int mi;
public:
int mj;
Test(int i);
Test(const Test& t);
int getMi();
};
Test::Test(int i)
{
mi = i;
}
//成员函数中可以直接访问对象的成员变量,哪怕是通过对象 '.'操作符来访问私有成员变量 都是合法的
Test::Test(const Test& t)
{
mi = t.mi;
}
int Test::getMi()
{
return mi;
}
int main()
{
const Test t(1);
return 0;
}