一.C++类与对象
1.基本单位是类。
2.类是数据和操作数据的函数的封装。
3.对象使用自己的方法完成对数据的操作。
4.类可以隐藏数据和操作细节,对象通过类结构与外部通信。
C++与C进行代码重用是通过类和函数来实现的。C++同时可以通过类来限定数据访问得的权限。
C++通过类的继承实现代码重用,类的封装实现权限封装,数据与代码合为一体。类的多态实现一个接口的多个功能。通过接口封装实现不同的权限。
类中包含三种类型的数据: private 私有数据类型 protected 保护类型 private 私有类型
1>三种类型的访问权限:
private | protected | public |
私有数据类型尽在类中可见 | 在该类和派生类中可见 | 提供外部的接口,外部可访问的数据及方法 |
class | struct | union |
默认下为私有数据类型和方法 | 默认情况下为公有public | 默认情况下为公有public |
1.允许已定义的类名出现在累的说明中。
2.类可以无名,用于直接申明对象。
3.类是一个程序包,可以只有数据成员或函数,或者为空,空类的对象大小不为零,空类占一个字节,表明类存在。空类中函数在代码区,不包括函数,大小占一个字节。
#include<iostream>
class kong
{
public:
//int num;
void go(int num)
{
std::cout << "12345" << std::endl;
}
};
void main()
{
kong kong1;
//kong1.num = 100;
//std::cout << sizeof(kong) << std::endl; 空类占用一个字节,表明类存在,代码不计入sizeof
std::cout << sizeof(kong) << std::endl;
std::cout << &kong1<< std::endl;
std::cin.get();
}
4.类中包含常量数据以及常量函数的情况
class myclass1
{
public:
int a;
const int b=0;//常量必须进行初始化
mutable int e;//不被const限制.
//限定不对成员变量赋值,但是可以对mutable数据赋值,
void set(int a) const
{
}
};
三.构造函数与析构函数
作用:分配空间,为对象成员赋值,请求其他资源
1.所有类都默认有一个构造函数,一个析构函数和拷贝构造函数。
2.构造函数和析构函数都可以重载,且没有返回值。
#include<iostream>
class myclass
{
public:
int num;
public:
//构造函数与析构函数的重载
myclass():num(4) //变量初始化方式二
{
//num = 4;变量 初始化方式1,
std::cout << "对象被建立"<<std::endl;
}
myclass(int a) //构造函数的重载
{
this->num = a;
}
~myclass()
{
std::cout << "对象被销毁"<<std::endl;
}
};
void run()
{
myclass classa,classb(8);//等价于classb=10;
std::cout << classa.num << " " << classb.num << std::endl;
}
void main1()
{
myclass *p = new myclass(10); //等价于*p=(new myclass(10))
p = new myclass(100);
run();
int num = 4;
int data(4);//调用int类型的构造函数
std::cin.get();
}
3.类中包含其他类时,所包含的类首先创建,然后该类创建。销毁时,该类先销毁,所包含的类后销毁。
#include<iostream>
//系统自动生成
class fushu
{
public:
fushu();
~fushu();
};
fushu::fushu()
{
std::cout << "fushu类的构造" << std::endl;
}
fushu::~fushu()
{
std::cout << "fushu类的销毁" << std::endl;
}
class math
{
public:
fushu fushu1;
math()
{
std::cout << "math类的构造" << std::endl;
}
~math()
{
std::cout << "math类的销毁" << std::endl;
}
};
void go()
{
math math1;
}
void main2()
{
go();//类创建过程:fushu类先创建,math类创建, 类销毁过程:math先销毁,然后fushu销毁
std::cin.get();
}
4.explicit 显式调用,不允许进行隐式类型转换。
#include<iostream>
#include<array>
#include<vector>
class classobj
{
public:
int num;
public:
explicit classobj(int data)
{
this->num = data;
std::cout << "类的创建以及数据初始化"<<num << std::endl;
}
~classobj()
{
std::cout << "被销毁" << num << std::endl;
}
protected:
private:
};
void main()
{
//classobj num = 5;//赋值号,类型转换
classobj data(5);// 创建对象必须选择合适的构造函数
//classobj class1[10];
//classobj *p = new classobj;
//classobj *p = new classobj(5);
//classobj *p = new classobj(5);
classobj obj(5);
std::array<classobj, 2> arg = {data,obj};
std::vector<classobj> arg1;
arg1.push_back(obj);
std::cin.get();
}
5.拷贝构造函数
1>类会默认生成,可以通过delete与default删除和生成默认的构造函数和拷贝构造函数。禁用拷贝构造函数,禁止别人拷贝数据。同时类还重载了“=”赋值运算符。
#include<iostream>
class classA
{
private:
int a;
int b;
public:
//classA(const classA & ca) //拷贝函数,如果没有定义,则自动生成
//{
//}
classA()
{
}
classA(int x,int y):a(x),b(y)//构造函数
{
/*a = x;
b = y;*/
}
void print()
{
std::cout << a << ' ' << b << std::endl;
}
};
void main1()
{ /*编译器会默认生成默认构造函数和默认拷贝构造函数*/
classA class1(7,8);
classA class2(class1);
class1.print();
class2.print();
std::cin.get();
}
class myclassA
{
public:
//myclassA() = delete; //删除默认构造函数
myclassA() = default;//默认生成构造函数
myclassA(const myclassA & )=delete;//删除默认拷贝构造函数
//~myclassA();
};
void main2()
{
myclassA myclass1;
}
2>深度拷贝构造与浅拷贝构造
浅拷贝,两个指针指向同一片内存,对内存中的值进行更新。深拷贝,重新申请内存,将传递过来的数据存储在新的内存中。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
class string
{
public:
char *p;
int length;
//获取内容,分配内存,拷贝内容
string(int num,char *str)
{
length = num;
p = new char[length];
memset(p, 0, length);
strcpy(p,str);
}
string(const string &string1)
{ //浅拷贝
//this->p = string1.p;
//this->length = string1.length;
//深拷贝,重新申请内存,将内容拷贝到新的内存空间中,被拷贝的内存空间被销毁,不影响目前的内存空间
this->length = string1.length;
this->p = new char[this->length];
memset(p, 0, length);
strcpy(this->p,string1.p); //字符串的拷贝
}
~string()
{
delete[]p;//销毁内存
}
};
void main()
{
string str1(10,"hello!");
string str2(str1);
std::cout << str1.p << std::endl;
std::cout << str2.p << std::endl;
string *pstr = new string(10, "hello!");
string *pstrr = new string(*pstr);
delete pstr;
std::cout << pstrr->p << std::endl; //(*pstr).p
std::cin.get();
}