CD10.【C++ Dev】类和对象(1)
目录
1.为什么要引入?
2.对比C语言的结构体
C++的结构体
1.不同结构体可以定义相同的函数
2.成员函数和成员变量的定义顺序是随意的
3.C++的类
1.格式
2.三种访问限定符
public
private和protected
3.访问权限的作用域
注意默认规则
4.类的成员函数的第二种定义方式
5.类里面定义的函数默认就是inline
★6.成员函数的形参和成员变量的命名规范
成员变量的命名建议
1.为什么要引入?
之前在CD1.【C++ Dev】C++的简单介绍文章中提到过"1979年,贝尔实验室的本贾尼在C语言的基础上进行扩展,增加了类的机制,完成了一个可以运行的预处理程序,称之为C with classes(带类的C)"
C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题
C++在C的基础上进行改进,基于面向对象的,即将一件事情拆分成不同的对象,靠对象之间的交互完
成
2.对比C语言的结构体
C语言结构体中只能定义变量,而在C++中,结构体内不仅可以定义变量,也可以定义函数
具体可以参见C24.【C++ Cont】结构体文章
C++的结构体
1.不同结构体可以定义相同的函数
原因:虽然是相同的函数,但是属于不同的类域,因此互不干扰
struct A
{
void function()
{
}
};
struct B
{
void function()
{
}
};
2.成员函数和成员变量的定义顺序是随意的
原因:成员变量写在前面或者后面都能找到,因为类域是整体
struct A
{
int a;
void function()
{
a = 1;//使用上方定义的a
}
};
或者
struct A
{
void function()
{
a = 1;//使用下方定义的a
}
int a;
};
在C++中,struct经常使用class来代替,例如写成下面这样:
class A
{
int a;
void function()
{
a = 1;
}
};
注意struct和class的格式:结尾有分号!
3.C++的类
C语言的数据和方法是分开的,C++将数据和方法封装到一起形成类
1.格式
class 类名
{
//类体
};
类体由成员变量和成员函数组成
2.三种访问限定符
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限(三种访问限定符)选择性的将其接口提供给外部的用户使用
public
即公有,顾名思义,其修饰的成员在类外可以直接被访问
例如下面代码对val的访问是合法的:
class A
{
public:
int val;
};
int main()
{
A a;
a.val=1;
}
像int val这样的都叫声明(没有提供空间);像A a这样的,为类的实例化(提供了空间),或者叫对象的定义,可以形象理解为蓝图(声明)和建筑物(实例化)
(备注:实例化是指在面向对象的编程中,把用类创建对象的过程称为实例化)
下面展示典型的错误访问:
class A
{
public:
int val;
};
int main()
{
A::val = 1;
}
A为类的声明,没有提供空间,不能访问
private和protected
private为私有,protected为保护,顾名思义,它们修饰的成员在类外不能直接被访问,但在类里可以直接访问
(暂且认为protected和private没有区别,具体的区别在继承中)
例如下面代码对val的访问是不合法的:
class A
{
private:
int val;
};
int main()
{
A a;
a.val=1;//无法直接访问
}
class A
{
protected:
int val;
};
int main()
{
A a;
a.val=1;//无法直接访问
}
3.访问权限的作用域
从该访问限定符出现的位置开始直到下一个访问限定符出现时为止,如果后面没有访问限定符,作用域到 } ,即类的结束
例如下方代码:
class A
{
public:
int val1;
char val2;
private:
short val3;
};
val1和val2都是公有的,val3是私有的
注意默认规则
1.class的默认访问权限为private,而struct为public(因为struct要兼容C语言)
但不建议使用默认的访问权限,最好显式说明!
2.访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别
4.类的成员函数的第二种定义方式
如果类中成员函数的声明和定义分离,那么需要指定类域(使用域作用限定符::)
class A
{
public:
void function();
};
void A::function()//指定类域
{
//do_something
}
注意:1.不能将成员函数的定义写在类声明之前 2.内联函数必须在类里面定义(具体原因参见CD8.【C++ Dev】auto、范围for、内联函数和nullptr文章)
5.类里面定义的函数默认就是inline
例如以下代码,在release下运行:
#include <iostream>
using namespace std;
class A
{
public:
inline int square(int x);
};
inline int A::square(int x)
{
return x * x;
}
int main()
{
A obj;
int ret=obj.square(3);
return 0;
}
转到反汇编:
发现:square()成员函数被展开为imul指令
★6.成员函数的形参和成员变量的命名规范
解释以下的代码中value=value语句的含义(换句话说哪个是形参?哪个是成员变量?)
class MyClass
{
public:
void setValue(int value)
{
value = value;
}
int value;
};
可以写一个测试代码来判断:
int main()
{
MyClass m;
m.value = 1;
m.setValue(10);
cout << m.value << endl;
return 0;
}
运行结果:
结论:当局部变量和成员变量同名时,局部变量优先,如果需要访问成员变量,可以使用this指针(这个之后在说)
成员变量的命名建议
成员变量名最前面或者在最后面加下划线_,就像下面这样:
#include <iostream>
using namespace std;
class MyClass
{
public:
void setValue(int value)
{
_value = value;
}
int _value;
};
int main()
{
MyClass m;
m._value = 1;
m.setValue(10);
cout << m._value << endl;
return 0;
}
运行结果: