打印
[菜农群课笔记]

Lee老师群课:C++之类,成员函数,this等

[复制链接]
2533|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tear086|  楼主 | 2011-4-30 09:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 hotpower 于 2012-9-22 13:20 编辑

John Lee<j.y.lee@yeah.net> 20:27:15
今天讨论,C++类的一般概念。
C++的类(class)是以C的结构(struct)为基础发展而来的。结构中的数据,在C++中称为“数据成员(data member)”。C++类与C结构之间的区别之一,是C++的类中可以定义函数,C++称为“成员函数(member function)”。在C程序中,struct中的数据都是公开的,程序中只要有一个struct的地址,就可以随便访问其中的数据。


雁塔菜农<hotwc3@qq.com> 20:29:25
实际只要会结构就应该会C++


John Lee<j.y.lee@yeah.net> 20:30:03
随着程序规模的增长,缺点就开始暴露、变大了,由于各个程序员的编程素质不同,某些程序员可能随意访问struct中的数据,造成了各模块之间的耦合性增大,最终,程序就变成了一团乱麻。


John Lee<j.y.lee@yeah.net> 20:30:37
C++的出现,在语法上就提供了限制这种随意性的机制,C++称为“数据隐藏”。


class c {
public:
    ...
private:
    int data;
    ...
};


c类定义中出现的“private”就是针对数据隐藏的新语法(关键字)。


在private之后的的数据定义,都具有了“私有”访问属性。


小飞(467503326) 20:34:01
C语言中也可以有函数吧 结构体里面


John Lee<j.y.lee@yeah.net> 20:34:28
可以的。


雁塔菜农<hotwc3@qq.com> 20:34:49
应该是函数指针吧


John Lee<j.y.lee@yeah.net> 20:36:03
例如:int data; 就是私有的


你无法通过一个该类的实例的地址来访问这个成员。


例如:
c inst;
inst.data++; // 编译报错


雁塔菜农<hotwc3@qq.com> 20:38:09
安全


李冬发(632653918) 20:40:31
成员函数


John Lee<j.y.lee@yeah.net> 20:40:31
要访问这些“隐藏了”的数据,必须通过另一种方法:类的“成员函数”。


雁塔菜农<hotwc3@qq.com> 20:40:47
高级语言的属性一般都是通过get(),set()来访问
即只读或只写???限制其访问


John Lee<j.y.lee@yeah.net> 20:43:00
但是,这并不意味着可以随意访问“隐藏”的数据,因为“成员函数”是由类提供的一段逻辑实现(函数),是可以决定怎样访问“隐藏”的数据。


从某种意义上说,使用某个类的应用程序,除了知道这个类中有一个私有数据的名字以外,就没有什么别的了。


甚至,私有数据的名字,都可以改成无意义的标识符。


例如,look中的sync_t类:
class sync_t {
public:
sync_t() __OPT_ATTR__;


protected:
base::task_t* wakeup(uintptr_t data, base::task_t* task = 0) __OPT_ATTR__;
base::task_t* do_wakeup(uintptr_t data, base::task_t* task = 0) __OPT_ATTR__;


protected:
uintptr_t internal_data;
};


里面有一个internal_data


你除了能“看见”它之外,别的什么都不能干。


雁塔菜农<hotwc3@qq.com> 20:48:24
动不了它


它躲在类里


John Lee<j.y.lee@yeah.net> 20:49:44
访问修饰符是:protected。外面的程序不能访问它。


C++为类中的成员提供了3中“访问修饰符”。


public, private, protected。


各个修饰符按出现的先后顺序起作用。


雁塔菜农<hotwc3@qq.com> 20:53:16
这就是比C安全的地方


就和访问结构里的成员变量一样


John Lee<j.y.lee@yeah.net> 20:53:15
public修饰的“数据成员”和“成员函数”,外部程序可以随意访问。


程序中,总有一些数据是不希望别的“模块”来访问的。


private修饰的,除了类的“成员函数”外,不允许其他程序访问。


protected修饰的成员,可以被“派生类”访问,而不允许其他程序访问。


如果还不了解“派生”的概念,protected就先不管它。


class c {
public:
    int get();
private:
    int data;
};


int c::get()
{
    return data;
}


这个就是一个非常简单的“成员函数”访问“私有”成员的例子。


int c::get()是 c 类的“成员函数”,int data是“私有的数据成员”。


根据上面描述的规则:成员函数可以访问私有数据,所以get()中是可以访问data的。


而get()本身又是一个public修饰的成员函数,能够被其他程序访问。


所以,从效果来看:“程序可以间接地读取data的值”。


但c类中没有提供“写”data的函数,所以data对程序来说,有“只读”的效果。


雁塔菜农<hotwc3@qq.com> 21:05:30
get()现在应该是只读的


John Lee<j.y.lee@yeah.net> 21:08:32
c inst1;
c inst2;
int val = inst1.get();


有两个c类的实例:inst1, inst2.


每个实例都应该有data数据成员。那么c::get()怎么知道应该读取哪一个实例的data?


在调用get之前,必须为其指明具体实例。


inst1.get();


或inst2.get();


我们知道,函数,其实就是一个地址,里面有代码。


而调用,就是把返回地址保存之后,跳转到函数的地址。


那么从调用的过程来看,get()是怎么知道应该访问哪个实例的data?


如果我们用C的方法,应该怎么办?


typedef struct {
    int data;
} c;


int get(c* p)
{
    return p->data;
}


c inst1;
c inst2;
int val = get(&inst1);


我们通过一个参数,来传递实例的地址。


get()函数里面,就很容易地访问对应的实例中的data了。


C++的方法完全与C一样。


只不过那个实例地址参数,被“隐含”了。


这个“隐含”的实例地址(指针),C++称为“this”。


this是C++的关键字。


除了this的“隐含”属性之外,所有的用法,与C的方法一样。


回到C++例子中:
int val = inst1.get();


编译器会使用inst1的地址作为this指针,调用c::get()函数。


在很多C程序中,可以看到某些函数的第1个参数,是一个struct的指针,而函数中,大部分也是对这个struct的成员进行操作,这个函数实际上就等于C++中的成员函数的作用。


“::”是C++的“作用域分辨运算符”。


表示::之后的成员的作用域限于::之前的类。


我们在C编程时,也有作用域的概念。


struct a {
   int data;
};


struct b {
   int data;
};


为了完整地表示data,必须在其之前加上作用域限定。


如:inst.data; p->data; 等等。


下面讲一点延伸的细节。


class c1 {
public:
    int foo();
    ...
};


class c2 {
public:
    int foo();
    ...
};


两个类:c1, c2 里都有成员函数 foo();


在C程序中,我们调用一个函数:
foo();


编译后的结果,对arm来说是:
bl foo


可能有的编译器会加上前置下划线:_
bl _foo


bl是arm指令。


对x86是:
call foo


6502是:
jsr foo


不管怎样,都会使用一个符号地址来表示调用的函数。


对C来说,函数不能同名,所以汇编的符号地址可以直接对应C的函数名。


但在C++上,就有麻烦了。


不同的类可以有同名的成员函数。


c1::foo();
c2::foo();


以后还会讲到的函数重载,都是同名函数。


那么如何映射到汇编的符号地址?


C++引人了一个概念:name mangling.


我以前看的书上称为“名字粉碎”


简单地说,汇编的符号地址,除了“函数名”外,还需要其他的元素来共同组成。


这些元素包括:名字空间名,类名,各个参数的类型等等。
最终组成的汇编符号,可能非常长。


回复John Lee<j.y.lee@yeah.net> 21:57:35
看见的部分,仅仅是函数名本身。


如果有模板(template),那么符号还会更加长,几百个字符都有可能的。


这个符号是为链接器(linker)准备的。


人看着基本都晕。




这里有一个实际的符号例子,给大家看看:
_ZN4look3edf12task_queue_t6insertERNS0_6task_tE
在这里讨论这个,只是告诉大家,编译器是可以区分同名函数的,不会搞错。

相关帖子

沙发
hotpower| | 2011-4-30 10:30 | 只看该作者
好!
有些人听完课就就溜人

使用特权

评论回复
板凳
Swallow_0322| | 2011-4-30 11:09 | 只看该作者
:$ 听了课但没做笔记的报到!

使用特权

评论回复
地板
hotpower| | 2011-4-30 17:04 | 只看该作者
楼主最近记笔记不错。

使用特权

评论回复
5
murex| | 2011-5-1 14:41 | 只看该作者
我是连听课都没听的,就跑来溜达一下,连记录都还没啥时间看,都一直在加班,一有时间是尽量睡觉了:loveliness:

使用特权

评论回复
6
hotpower| | 2011-5-1 18:40 | 只看该作者
笔记比他第一次好多了。

使用特权

评论回复
7
oumeng| | 2011-6-21 21:11 | 只看该作者
恩,学习了

使用特权

评论回复
8
bin8| | 2011-7-1 13:49 | 只看该作者
深受教益,非常清晰,谢谢老师

使用特权

评论回复
9
uniquehope| | 2011-7-1 16:43 | 只看该作者
正准备学习c++,围观下~~:lol

使用特权

评论回复
10
yangaiping| | 2011-7-3 16:48 | 只看该作者
准备学C++,围观下!

使用特权

评论回复
11
gagmeng| | 2011-8-19 15:06 | 只看该作者
开始慢慢看LOOK了,出差啊,偷偷看看,国庆后开始做LOOK志愿者了

使用特权

评论回复
12
flywater2010| | 2011-8-25 14:07 | 只看该作者
学习中.....

使用特权

评论回复
13
电子write_cai| | 2011-8-25 20:45 | 只看该作者
看得懂

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:個人博客:yuphone.cnblogs.com 聯絡方式:張亞峰 15013013265@qq.com

0

主题

120

帖子

3

粉丝