首页 > 代码库 > C++OOP之类和对象 ---第一个特征:数据抽象
C++OOP之类和对象 ---第一个特征:数据抽象
C++中的结构体:(不可访问整个结构体,如:不能一次输出结构体。)
1):在C中,结构体只可以含有成员,不可以有函数,但是c++中可以。而且,函数可以直接访问里面的数据成员。
2):访问方式
a):若是结构体类型的 变量, 采用 . 形式。如:Person.Age_。
b):若是结构体类型的 指针, 则采用 -> 形式。如 it->Age_.
类:
1):类的访问属性:(默认是private)
public:元素师公开的,任何位置都可以访问;
private:成员是私有的,只能在类的内部访问。
我们一般采用的方案是:把 类的成员变量 设为private, 把 类的成员函数 设为public。
这样我们只能通过 函数 设置或者获取其成员变量的值。
示例代码如下:
#include <iostream>#include <string>using namespace std;class Person { private: int _id; string _name; int _age; public: int get_id() const //保护本对象 { return _id; } void set_id(int id) { _id = id; } string get_name() const { return _name; } void set_name(const string &name) { _name = name; } int get_age() const { return _age; } void set_age(int age) { _age = age; } void print(std::ostream &os) { os << "id: " << _id << " name: " << _name << " age: " << _age << endl; }};int main() { //编译错误,不可以直接访问。
/* Person p1; p1._age = 99; p1._id = 00123; p1._name = "Jack"; p1.print(cout); Person *p2 = new Person; p2->_age = 34; p2->_id = 12345; p2->_name = "hello"; p2->print(cout);*/
//修改如下:
Person p;
p.set_age(23);
p.set_id(1234);
p.set_name("zhangsan");
p.print(cout); }
2): 成员函数:
四要素: 函数返回类型, 函数名, 形参表, 函数体。
注意:
a): 成员函数含有额外的形参;
调用成员函数是,实际上是使用对象来调用的,例如p1.print(cout),在此调用中,传递了对象cout,但是print 是如何知道打印 哪个对象的属性呢? 因此,这里实际上 把 p1 也作为一个参数传递给print。
b):this 指针的引入(用于解决返回自身的值或者引用):
每一成员函数都有隐含的形参 就是 this 指针。 这个参数 指向调用对象的地址。
例如在 p1。print(cout)中,print中的this指针 就指向 p1 的地址。
c):const成员函数:
如:string get_name() const
此处const的含义是, get_name这个函数不能修改 本对象。其实就是不得对 类的数据成员进行修改。
注意: 普通对象可以调用const函数,也可以调用非const函数, 但是const对象只能调用const对象。(语义--->只读)
4):const成员函数 和 普通函数可以构成重载。
const成员 必定 调用 const 成员函数。
重载的要素: 函数名(必须一样), 函数形参表, 类的名称, 成员函数的const属性。
C语言中没有函数重载, 因为C函数 的唯一标识 是 函数名称。(产生重定义);
而C++ 函数的唯一标识 是 函数名称 和 参数表 构成。
1 void print(std::ostream &os) 2 { 3 os << "id: " << _id << " name: " << _name << " age: " << _age << endl; 4 } 5 6 void print(std::ostream &os) const 7 { 8 os << "id: " << _id << " name: " << _name << " age: " << _age << endl; 9 }10 };11
5):构造函数
构造函数式特殊的成员函数,与类同名,且没有返回类型 ;
一个类 可以有多个构造函数,构造函数必有不同数目或者类型的形参列表。
注意:每个类都有默认的构造函数,当我们自己定义了一个新的构造函数时,如果我们不显式写出默认构造函数,程序将会 自动执行 我们新定义的构造函数。这就可能造成已写错误。
示例代码如下:
1 class Person 2 { 3 public: 4 //修改之处:增加默认构造函数即可 5 Person() //默认构造函数 6 :Age_(0),Name_("") 7 { } 8 9 Person(int age, const string name)10 :Age_(age),Name_(name)11 { }12 13 private:14 int Age_;15 string Name_;16 }17 18 int main()19 {20 Person p1;//编译错误。没有显式提供默认构造函数。21 Person p2(23, "zhangsan"); //ok22 }
构造函数之初始化式:(如上示例代码)
必须使用初始化列表的情形:
i):没有默认构造函数的类成员;
ii):const成员;
iii):引用类型的成员;
iiii)类成员需要显式调用含参数的构造函数。
考虑下面的类:
class X{ private: int i; int j; public: X(int val) //若 val 为 35, 则 i=0 ;j = 35; :j(val),i(j) {}};
我们设想的是 用 val 初始化 j, 用 j 的值初始化 i,然而这里初始化的次序 是 先 i 后 j;
6):析构函数:
~Person()
{}
再谈this指针:this指针最大的作用就是返回自身的引用。
示例代码如下:
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 class Person { 6 private: 7 int _id; 8 string _name; 9 int _age;10 11 public:12 13 Person() :14 _id(-1), _name("none"), _age(-1) 15 {16 }17 18 Person(int id, const string &name, int age) :19 _id(id), _name(name), _age(age) 20 {21 }22 23 Person &set_id(int id) 24 {25 _id = id;26 return *this;27 }28 29 Person &set_name(const string &name) 30 {31 _name = name;32 return *this;33 }34 35 Person &set_age(int age) 36 {37 _age = age;38 return *this;39 }40 41 Person &print(std::ostream &os)42 {43 os << "id: " << _id << " name: " << _name << " age: " << _age << endl;44 return *this;45 }46 47 const Person &print(std::ostream &os) const48 {49 os << "id: " << _id << " name: " << _name << " age: " << _age << endl;50 return *this;51 }52 53 };54 55 int main(int argc, char **argv) {56 Person p;57 p.print(cout);58 p.set_id(12).print(cout).set_age(22).print(cout).set_name("hello").print(59 cout);60 }61
上述程序 运行结果为:12,22,helllo 并且 其调用的print函数 都是 Person print()类型。
(若加上析构函数,则1次销毁)。
若不加 &,则运行的是 同意对象的 多个副本。总共7个。 调用几次成员函数,则生成几个副本。
(若加上析构函数,则7次“销毁”)
Static:
static变量不能与this指针绑定。既然static变量属于整个类,那么 就不属于特定的某一个对象。
而this是与特定对象绑定在一块的。
C++OOP之类和对象 ---第一个特征:数据抽象