一、C++类&对象
1、定义:
类(class)是一种将数据和函数组织在同一个结构里的逻辑方法。定义类的关键字为class ,其功能与C语言中的struct类似,不同之处是class可以包含函数,而不像struct只能包含数据元素。类中的数据和函数都称为类的成员。
类定义是以关键字 class 开头,后跟类的名称。类的主体是包含在一对花括号中。类定义后必须跟着一个分号或一个声明列表。例如:
class box; //class+名字
{
public:
double length;
double breadth;
double height;
};//不要忘记最后加分号
2、对象定义:声明类的对象,就像声明基本类型的变量一样。下面的语句声明了类 Box 的两个对象:这两个对象都有各自的数据成员
box box1;//声明box1,类型为box
box box2;
3、
类的对象的公共数据成员可以使用直接成员访问运算符 (.) 来访问
#include <iostream>
using namespace std;
class Box
{
public:
double length; // 长度
double breadth; // 宽度
double height; // 高度
};
int main()
{
Box Box1; // 声明 Box1,类型为 Box
Box Box2; // 声明 Box2,类型为 Box
double volume = 0.0; // 用于存储体积
// box 1 详述
Box1.height = 5.0;
Box1.length = 6.0;
Box1.breadth = 7.0;
// box 2 详述
Box2.height = 10.0;
Box2.length = 12.0;
Box2.breadth = 13.0;
// box 1 的体积
volume = Box1.height * Box1.length * Box1.breadth;
cout << "Box1 的体积:" << volume << endl;
// box 2 的体积
volume = Box2.height * Box2.length * Box2.breadth;
cout << "Box2 的体积:" << volume << endl;
return 0;
}
- 在类内部进行函数的声明和定义,此种方式我们成为inline,也即内联定义。inline是C++关键字,专门用于表示内联;
- 在类内进行函数声明,在类外部进行函数定义。
class Box{ public: double length; // 长度 double breadth; // 宽度 double height; // 高度 double getVolume(void) { return length * breadth * height; }};
class student
{
char name[20]; //姓名
int id_num; //学号
int age; //年龄
char sex; //性别
void set_age(int a);
int get_age()const;
};
//在类外部定义set_age函数
void student::set_age(int a)
{
age = a;
}
//在类外部定义get_age函数
int student::get_age()const
{
return age;
}
class student
{
char name[20]; //姓名
int id_num; //学号
int age; //年龄
char sex; //性别
inline void set_age(int a);
inline int get_age();
};
//在类外部定义set_age函数
void student::set_age(int a)
{
age = a;
}
//在类外部定义get_age函数
int student::get_age()
{
return age;
}
#include <iostream>
using namespace std;
class Line
{
public:
double length;
void setLength(double len);
double getLength(void);
};
// 成员函数定义
double Line::getLength(void)
{
return length;
}
void Line::setLength(double len)
{
length = len;
}
// 程序的主函数
int main()
{
Line line;
// 设置长度
line.setLength(6.0);
cout << "Length of line : " << line.getLength() << endl;
// 不使用成员函数设置长度
line.length = 10.0; // OK: 因为 length 是公有的
cout << "Length of line : " << line.length << endl;
return 0;
}
#include <iostream>
using namespace std;
class Box
{
protected:
double width;
};
class SmallBox :Box // SmallBox 是派生类,从父类 Box 派生了一个子类 smallBox。
{
public:
void setSmallWidth(double wid);
double getSmallWidth(void);
};
// 子类的成员函数
double SmallBox::getSmallWidth(void)//width 成员可被派生类 smallBox 的任何成员函数访问。
{
return width;
}
void SmallBox::setSmallWidth(double wid)
{
width = wid;
}
// 程序的主函数
int main()
{
SmallBox box;
// 使用成员函数设置宽度
box.setSmallWidth(5.0);
cout << "Width of box : " << box.getSmallWidth() << endl;
return 0;
}
class Box
{
double width;//只有类和友元函数可以访问私有成员,默认的是private
public:
double length;
void setWidth(double wid);
double getWidth(void);
};
1.private 成员只能被本类成员(类内)和友元访问,不能被派生类访问;
-
2. protected 成员可以被派生类访问。
4、类的构造函数与析构函数
(1)默认构造函数。以Student类为例,默认构造函数的原型为
Student();//没有参数
(2)初始化构造函数
Student(int num,int age);//有参数
(3)复制(拷贝)构造函数
Student(Student&);//形参是本类对象的引用
(4)转换构造函数
Student(int r) ;//形参时其他类型变量,且只有一个形参
void Line::setLength( double len )
{
length = len;
}
double Line::getLength( void )
{
return length;
}
class student
{
public:
//默认构造函数,没参数
student()
{
num = 1001;
age = 18;
}
//初始化构造函数,有参数
student(int n, int a) :num(n), age(a){}
private:
int num;
int age;
};
int main()
{
//默认构造函数初始化对象s1;
student s1;
//初始化构造函数初始化对象s2;
student s2(1002, 18);
return 0;
}
student s2(1002, 1008);
student s3(s2);//将对象s2复制给s3
通过使用另一个同类型的对象来初始化新创建的对象。
复制对象把它作为参数传递给函数。
复制对象,并从函数返回这个对象。
classname(const classname &obj)//obj是一个对象引用,该对象用于初始化另一个对象
{
//构造函数的主体
}
#include <iostream>
using namespace std;
class Line
{
public:
int getlength(void);
Line(int len);//简单的构造函数
Line(const Line &obj);//拷贝构造函数
~Line();//析构函数
private:
int *ptr;
};
//成员函数定义,包括构造函数
Line::Line(int len)
{
cout << "调用构造函数" << endl;
//为指针分配内存
ptr = new int;
*ptr = len;
}
//拷贝构造函数
Line::Line(const Line &obj)
{
cout << "调用拷贝构造函数并为指针ptr分配内存" << endl;
ptr = new int;
*ptr = *obj.ptr;//拷贝值
}
//析构函数
Line::~Line(void)
{
cout << "释放内存" << endl;
delete ptr;
}
int Line::getlength(void)
{
return *ptr;
}
void display(Line obj)
{
cout << "Line 大小" << obj.getlength() << endl;
}
int main()
{
Line line(10);
display(line);
return 0;
}
student(int r)
{
int num = 1004;
int age=r
}
1,当对象被声明为全局变量,则当整个程序退出时,其析构函数才会被调用。
2,当对象被声明为自动存储类型(局部变量),当其生命周期结束,即其作用域执行完毕时,其析构函数会被调用。
3,当对象被声明为指针变量(使用new创建对象),当执行到delete方法时,其析构函数会被调用。
2 )这个友元函数他不属于该类的成员函数,他是定义在类外的普通函数,只是在类中声明该函数可以直接访问类中的 private 或者 protected 成员
#include <iostream>
using namespace std;
class Box
{
double width;
public:
friend void printwidth(Box box);//友元函数
void setwidth(double wid);
};
//成员函数定义
void Box::setwidth(double wid)
{
width = wid;
}
//printwidth()不是任何类的成员函数
void printwidth(Box box)
{
/* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */
cout << "width of box:" << box.width << endl;
}
int main()
{
Box box;
//使用成员函数设置宽度
box.setwidth(10);
//使用友元函数输出宽度
printwidth(box);
return 0;
}
6、C++中的this 指针
this是指向实例化对象本身时候的一个指针,里面存储的是对象本身的地址,通过该地址可以访问内部的成员函数和成员变量。
关于this指针的一个精典回答:
当你进入一个房子后,
你可以看见桌子、椅子、地板等,
但是房子你是看不到全貌了。
对于一个类的实例来说,
你可以看到它的成员函数、成员变量,
但是实例本身呢?
this是一个指针,它时时刻刻指向你这个实例本身。
this的使用:1)在类的非静态成员函数中返回对象的本身时候,直接用return *this(常用于操作符重载和赋值、拷贝等函数)。2)传入函数的形参与成员变量名相同时,例如:this->n = n (不能写成n=n)
this 指针指向当前的对象
#include<iostream>
using namespace std;
//this指针保存了当前对象的地址,并且应用指针的形式指向了当前的对象
class A
{
public:
int get() const { return i; }
//this->i=x;这句话就表示把x的值赋值给当前的对象的私有成员函数i
void set(int x){ this->i = x; cout << "this 指针保存的地址是:" << this << endl; }
private:
int i;
};
int main()
{
A a;
a.set(9);
cout << "对象a所在内存地址为:" << &a << endl;
cout << "对象a保存的值为" << a.get() << endl;
cout << endl;
A b;
b.set(999);
cout << "对象b所在内存地址为:" << &b << endl;
cout << "对象b保存的值为" << b.get() << endl;
return 0;
}
7、指向类的指针
访问指向类的指针的成员,需要使用成员访问运算符 ->
#include <iostream>
using namespace std;
class Box
{
public:
//构造函数定义
Box(double l = 2.0, double b = 2.0, double h = 2.0)
{
cout << "constructor called" << endl;
length = l;
breadth = b;
height = h;
}
double volume()
{
return length*breadth*height;
}
private:
double length;
double breadth;
double height;
};
int main()
{
Box Box1(3.3, 1.2, 1.5);
Box Box2(8.5, 6.0, 2.0);
Box *ptrBox;//定义指向类的指针
//保存第一个对象的地址
ptrBox = &Box1;
//现在尝试使用成员访问运算符来访问成员
cout << "volume of Box1" << ptrBox->volume() << endl;
//保存第二个对象的地址
ptrBox = &Box2;
cout << "volume of Box2" << ptrBox->volume() << endl;
return 0;
}
8、C++类的静态成员
静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。所以在所有对象中都可以共享它。使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。
静态成员的定义或声明要加个关键static。静态成员可以通过双冒号来使用即<类名>::<静态成员名>。
#include <iostream>
using namespace std;
class Box
{
public:
static int objectCount;
// 构造函数定义
Box(double l=2.0, double b=2.0, double h=2.0)
{
cout <<"Constructor called." << endl;
length = l;
breadth = b;
height = h;
// 每次创建对象时增加 1
objectCount++;
}
double Volume()
{
return length * breadth * height;
}
private:
double length; // 长度
double breadth; // 宽度
double height; // 高度
};
// 初始化类 Box 的静态成员
int Box::objectCount = 0;
int main(void)
{
Box Box1(3.3, 1.2, 1.5); // 声明 box1
Box Box2(8.5, 6.0, 2.0); // 声明 box2
// 输出对象的总数
cout << "Total objects: " << Box::objectCount << endl;
return 0;
}
静态成员函数
静态成员函数与普通成员函数的区别:
- 静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。
- 普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针。
注意事项:
1、静态数据成员必须单独初始化
2、静态成员函数不能调用非静态成员函数与非静态数据成员
3、静态数据成员只有一份。