C++ 学习笔记03
一、访问权限
public: 公有权限 程序的任何位置都可以使用
protected: 受保护的,派生类和类的内部使用。什么叫派生类?等讲完继承才能用。
private: 私有的,只有类的内部可以使用。
类的内部:类的成员函数。
类的内部 | 派生类 | 全局 | |
---|---|---|---|
public | √ | √ | √ |
protected | √ | √ | × |
private | √ | × | × |
示例1
#include <iostream>
using namespace std;
class Person
{
private://私有权限
int money;//私有
int house;;//私有
int phone;;//私有
public://公有权限
void setInfo(int m, int h, int p) //公有
{
money = m;
house = h;
phone = p;
}
void show()//公有
{
cout<<money<<" "<<house<<" "<<phone<<endl;
}
};
int main()
{
Person p;
p.money = 10;//语法错误,因为main函数不是
//Person类的成员函数,所以不能使用Person类的私有成员
p.setInfo(5,6,7);
p.show();
}
练习1
定义类Array 向数组中输入整数 并求出数组元素中的最大值,最小值和平均值
- 数组成员变量private修饰
int * p;
int length; - 成员函数input(int length);
length为数组的长度;
数组动态创建new(按照输入的长度,创建数组)
功能:cin方式,输入数组的值 - 成员函数 int max(); 要求带返回值
- 成员函数 int min();
- 成员函数 int avg();
#include <iostream>
using namespace std;
class Array
{
private:
int* p;
int length;
public:
void input(int l)
{
length = l;
p = new int[length];
for(int i = 0;i < length;i++)
{
cout<<"请输入一个整数"<<endl;
cin>>p[i];
}
}
int max()
{
int m = p[0];
for(int i = 1;i < length;i++)
{
if(p[i] > m)
{
m = p[i];
}
}
return m;
}
int min()
{
int m = p[0];
for(int i = 1;i < length;i++)
{
if(p[i] < m)
{
m = p[i];
}
}
return m;
}
int avg()
{
int sum = 0;
for(int i = 0;i < length;i++)
{
sum += p[i];
}
return sum/length;
}
};
int main()//main输出函数的返回值
{
Array a;
a.input(5);
cout<<a.max()<<endl;
cout<<a.min()<<endl;
cout<<a.avg()<<endl;
return 0;
}
二、封装性
封装的概念
成员变量:在程序设计中不是每个属性都需要对外公开(女人不公开体重跟年龄,男人不公开身高及收入),
而有一些类的属性是对外公开的(名字、性别等);
因此在设计类时必须在类的表示法中定义属性和行为的公开级别,将不对外公开的属性使用private进行修饰。
但因为被private修饰,所以外部无法对其进行写入与读取的操作。
所以我们可以在public下留出读(getXXX())或写(setXXX())的操作函数;
示例2
#include <iostream>
#include <string>
using namespace std;
class Person{
private://类中的成员成员变量,如果没有特殊需要,不可以写成public
int money;
int id ;
public:
string name;
public:
void init(string n,int m,int i){
name = n;
money = m;
id = i;
}
int getMoney(){
return money;
}
//使用函数对成员变量读写,可以把成员变量的值控制在允许的范围内。
//如果直接把成员变量写成public的,则没有办法去控制它的值。
//setXXX 和getXXX只是命名的习惯,这种命名方式不是语法的要求。
void setMoney(int m)
{
if(m < money)
return;
money = m;
}
void setId(int i){
id = i;
}
int getId(){
return id;
}
};
int main()
{
Person p;
p.init("zhangsan",10000,1);
cout << p.getId() << "." << p.name << " have " <<p.getMoney() << " dollars " <<endl ;
return 0;
}
封装:
- 将具有相同属性和行为的一系列对象封装成一个类,将一系列重复性的代码封装成函数;
- 数据的隐藏,将不对外公开的属性和行为使用private进行修饰,保证数据安全。
练习2
创建一个类Product,成员变量name,price,使用set和get进行赋值与获取,在主函数创建三个产品对象并赋值,打印.
#include <iostream>
using namespace std;
class Product
{
private:
string name;
int price;
public:
void setName(string n)
{
name = n;
}
string getName()
{
return name;
}
void setPrice(int p)
{
price = p;
}
int getPrice()
{
return price;
}
};
int main()
{
Product p1;
p1.setName("手抓饼");
p1.setPrice(6);
Product p2;
p2.setName("烤冷面");
p2.setPrice(7);
Product p3;
p3.setName("麻辣烫");
p3.setPrice(20);
cout<<p1.getName()<<" "<<p1.getPrice()<<endl;
cout<<p2.getName()<<" "<<p2.getPrice()<<endl;
cout<<p3.getName()<<" "<<p3.getPrice()<<endl;
return 0;
}
三、分文件定义类
示例3
在类外部实现成员函数
#include <iostream>
using namespace std;
class Person
{
private:
int age;
public:
void setAge(int a);//类的内部只做函数的声明
void show();
};
void Person::setAge(int a)//Person:: 告诉编译器,这是Person类中的成员函数
{
age = a;
}
void Person::show()
{
cout<<age<<endl;
}
int main()
{
Person* p = new Person;
p->setAge(18);
p->show();
}
示例4
分.h和.cpp
main.cpp
#include <iostream>
#include "person.h"
int main()
{
Person* p = new Person;
p->setAge(18);
p->show();
}
person.h
#ifndef PERSON_H
#define PERSON_H
class Person
{
private:
int age;
public:
void setAge(int a);
void show();
};
#endif
person.cpp
#include "person.h"
#include <iostream>
using namespace std;
void Person::setAge(int a)
{
age = a;
}
void Person::show()
{
cout<<age<<endl;
}
练习3
定义一个类Cube ,数据成员:length,width,height (分文件)
成员函数如下功能:
1.由键盘输入长方体的长宽高input();
2.计算长方体体积int volume();
3.输出长方体体积show();
建议文件的名字和类的名字保持一致。
Cube.h
Cube.cpp
main.cpp
Cube.h
#ifndef _CUBE_H_
#define _CUBE_H_
class Cube
{
private:
int length;
int width;
int height;
public:
void input();
int volume();
void show();
};
#endif
Cube.cpp
#include "Cube.h"
#include <iostream>
using namespace std;
void Cube::input()
{
cin>>length>>width>>height;
}
int Cube::volume()
{
return length*width*height;
}
void Cube::show()
{
cout<<volume()<<endl;
}
main.cpp
#include "Cube.h"
#include <iostream>
using namespace std;
void Cube::input()
{
cin>>length>>width>>height;
}
int Cube::volume()
{
return length*width*height;
}
void Cube::show()
{
cout<<volume()<<endl;
}
四、构造函数
1.构造函数的作用和语法
在创建对象的时候会自动调用的函数,是c++中特殊成员函数。
主要作用是在创建对象时初始化对象,为对象的成员变量赋值
对象的初始化:参考如下代码
class Tank
{
private:
int m_iposX;
int m_iposY;
public:
void init()
{
m_iposX = 0;
m_iposY = 0;
}
};
int main()
{
Tank t1;
t1.init();
Tank t2;
t2.init();
return 0;
}
对象的初始化: 有且仅初始化一次,根据条件初始化
思考:
如何能避免误操作呢
初始化函数 如何避免误操作
忘记调用初始化函数
重复调用初始化操作
2.构造函数的规则和特点
创建语法如下:
- 名字必须与类同名 无返回值 可能有参数
- 访问权限一般是public,一旦私有构造函数,那么在类的外部将不能创建对象。
- 用户不能调用构造函数 只有在类对象创建时 自动调用
- 实例化对象时,只用到一个构造函数
示例5
无参构造函数
#include<iostream>
using namespace std;
class Person
{
private:
string name;
int age;
public:
Person()//构造函数
{
cout<<"i am constructor...."<<endl;
}
void show()
{
cout<<"我是"<<name<<" 今年"<<age<<endl;
}
};
int main()
{
Person x;//创建对象的时候,自动调用构造函数
Person b;
}
示例6
无参构造函数 成员变量赋值
#include<iostream>
using namespace std;
class Person
{
private:
string name;
int age;
public:
Person()
{
name="guanyu";//在构造函数中给成员变量赋值
age = 0;
}
void show()
{
cout<<"我是"<<name<<" 今年"<<age<<endl;
}
};
int main()
{
Person x;
x.show();
}
示例7
有参构造函数
class Person
{
public:
Person()
{
age = 10;
cout<<"无参构造函数"<<endl;
}
Person(int a)//重载一个有参的构造函数
{
age = a;
cout<<"create a...."<<endl;
}
void show()
{
cout<<age<<endl;
}
private:
int age;
};
int main()
{
Person x; //执行无参构造
x.show();
Person p1(20);//创建对象时,给构造函数传入实参列表。 执行有参构造
p1.show();
Person* p2 = new Person(40);//执行有参构造
p2->show();
}
3.默认构造函数
显示---->隐式
1)默认构造函数,当没有显式的定义构造函数时,系统会自动生成一个默认构造函数,
2)没有参数也没有逻辑;仅仅为了有构造函数而存在。
3)一旦显式的定义了构造函数,将不会生成默认构造函数
示例8
#include <iostream>
using namespace std;
class Person
{
private:
int age;
public:
Person(int a)//因为在这里显示的定义了一个构造函数,所以现在
//整个类中只有一个构造函数,所以创建对象的时候必须给实参列表
{
age = a;
}
//如果这里不显示的定义构造函数,会有一个默认构造函数,没有参数没有逻辑
//所以创建对象的时候不能有参数
};
int main()
{
Person p(1);
return 0;
}
练习4
计算长方形周长 构造函数实现长宽赋值(构造函数带参数) 分文件写!show()函数输出周长的值
Rect.h
#ifndef _RECT_H_
#define _RECT_H_
class Rect
{
private:
int width;
int height;
public:
Rect(int w, int h);
void show();
};
#endif
Rect.cpp
#include "Rect.h"
#include <iostream>
using namespace std;
Rect::Rect(int w, int h)
{
width = w;
height = h;
}
void Rect::show()
{
cout<<2*(width+height)<<endl;
}
main.cpp
#include "Rect.h"
int main()
{
Rect r1(1,2);//给构造函数传参数,注意不是直接调用构造
r1.show();
Rect* r2 = new Rect(3,4);
r2->show();
delete r2;
return 0;
}
4.构造函数的初始化列表
构造函数用冒号形式引出初始化列表
格式:成员变量名(初始值)
注意: 初始化成员列表的顺序应该和成员声明的顺序保持一致,不建议使用成员初始化其他成员
成员的初始化顺序,是按照声明的顺序进行,和初始化列表的顺序没有关系。
示例9
#include <iostream>
using namespace std;
class Rect
{
private:
int width;
int height;
public:
Rect(int w, int h):width(w),height(h)//初始化列表,用w初始化成员width,用h初始化成员height,初始化列表只能初始化成员变量 ()可以是构造函数的参数,也可以是常量
{
}
int perimeter()
{
return width*2+height*2;
}
};
int main()
{
Rect* p = new Rect(10, 20);
cout<<p->perimeter()<<endl;
Rect r(10, 20);
cout<<r.perimeter()<<endl;
}