类:是一种自定义的数据类型
对象:用类这种数据类型定义的变量
ps:回忆c语言中的结构体:用来描述一类事物属性的自定义的数据类型
实际的事物不光有属性(变量)还有行为(函数)
所以:就需要一种自定义的数据类型能够定义变量,也能够定义函数
c++:结构体和类就满足要求
定义类:
class 类名
{
成员变量;
成员函数;
};
定义对象:类名 对象名;--->实例化对象 栈区
类名 *p = new 类名; 堆区 delete p;
类:抽象的概念,是用来描述一类事物的属性和行为的抽象概念
对象:具体的事物
总结1:c语言的结构体和c++的结构体的区别?
1、c语言的结构体中不能定义函数,但是c++的结构体中可以定义函数
2、c语言的结构体定义类型名是struct 结构体名,但是在c++中可以将struct省略掉
总结2:c++的结构体和类的区别?
c++的结构体默认的访问限定符是public的,而类的访问限定符默认是private的
访问限定符:public protected private
1) public:可以被该类的成员函数、子类的函数和其友元函数访问,也可以被该类的对象访问。
2) protected:可以被该类的成员函数、子类的函数和其友元函数访问,但不能被该类的对象访问
3) private:只能由该类的成员函数和其友元函数访问,不能被其他函数访问,也不能被该类的对象访问。
代码示例:
#include
using namespace std;
class demo
{
public:
void getint()
{
cout<<"ival="<ival=ival;
}
private:
int ival;
};
class demo1
{
public:
void setint(int a,int b);//声明成员函数
void getint();
private:
int x;
int y;
};
void demo1::setint(int a, int b)
{
x=a;
y=b;
}
void demo1::getint()
{
cout<<"x="<getint();
demo &obj1=obj;//定义了一个对象引用
obj1.getint();//100
obj1.setint(200);
obj1.getint();//200
obj.getint();//200
#endif
demo obj;
obj.setint(300);
obj.getint();//类对象可以访问类中的公有成员
//obj.setint(200);//类对象不能访问类中保护成员
//obj.ival=800;//类对象不能访问类中的私有成员
demo1 obj1;
obj1.setint(300,500);
obj1.getint();
return 0;
}
封装:将一类事物的属性和行为用类这种自定义的数据类型包起来,并将可以暴露的暴露出来,将需要隐藏的隐藏起来
作用:给类对象的成员变量初始化
什么时候调用构造函数?
当用类创建对象时,系统会自动调用构造函数去初始化对象的成员变量,而且只会调用一次。
特点: 1 )函数名与类名相同
2 )无返回值
3 )构造函数是类中的成员函数
4 )如果一个类中没有显示定义构造函数,则系统会提供默认构造函数,
默认构造函数无参
5 )如果自定义了构造函数,系统将只会调用自定义的构造函数。
6 )构造函数无需用户主动调用,在创建对象时,系统自动调用构造函数,
而且只会调用一次
7 )构造函数可以重载
8 )构造函数可以用函数体赋值的方式初始化变量;也可以用初始化列表
的方式初始化
9 )构造函数如果定义成非公有,则该类无法创建对象(限制构造函数)
10 )构造函数没有this指针,因为调用构造函数时才开始创建对象,对象还未创建好,就不会有对象的地址。
*普通构造函数
1)无参构造函数
2)有参构造函数
3)有默认的参数的构造函数
*默认构造函数
如果类中没有显示定义一个构造函数,编译器会提供一个默认的构造函数(无参)
*限制构造函数
构造函数非公有,就叫做限制构造函数。
类中若有限制构造函数,该类无法实例化对象
代码示例:
#include
using namespace std;
class demo
{
public:
#if 0
demo(void) //无参构造函数
{
ival=300;
cout<<"demo(void)-----------\r\n";
}
#endif
#if 0
demo(int val)//有参构造函数
{
ival=val;
}
#endif
demo(int val=123)//有默认参数的构造函数
{
ival=val;
}
void setint(int val)
{
ival=val;
}
void getint()
{
cout<<"ival=="<
拷贝构造函数--》复制构造函数
作用:用一个已经存在的对象去初始化新定义的对象
特点:
默认拷贝构造函数
如果类中没有显示写拷贝构造函数,则编译器提供一个默认拷贝构造函数。
自定义拷贝构造函数
特点:没有返回值,函数名与类名相同,一般只有有一个入参,而且必须是
对象的引用。(参数可以多个,但是第一个参数必须是对象的引用,
后边其他参数只能是默认参数)
demo obj2(obj1)
demo(demo &obj,int val=0)
*深拷贝&浅拷贝
深拷贝:只复制数据,不复制指针,每个指针指向独立的内存
浅拷贝:只复制指针,多个指针指向同一个内存
人:{静态属性+动态属性}
静态:name age height weight
动态:eat() sleep() study() walk()..
C语言:用结构体来表示人的静态属性;在结构体外用函数来实现人的动态行为。
struct person zhangsan;
eat(zhangsan)
关联:通过函数入参可以将人的属性和行为关联起来
c++:将人的静态属性和动态行为封装在一个闭包中,动态行为就是用来操作静态
属性所描述的对象的。
class person
{
public:
char name[50];
int age;
protected:
float height;
float weight;
private:
eat();
sleep();
study();
walk();
}
#include
using namespace std;
class demo
{
public:
demo(int val)//普通构造函数
{
ival=val;
cout<<"demo(int val)------------\r\n";
}
//没有显示定义拷贝构造函数,编译器提供一个默认的拷贝构造函数
void setint(int val)
{
ival=val;
}
void getint()
{
cout<<"ival=="<
作用:当对象的生命周期结束时,释放对象所占的系统资源
特点:1 函数名和类名相同,函数名前加~
2 没有返回值,没有入参
3 析构函数是类中的成员函数
4 有默认的析构函数,如果没有自定义析构函数,编译器会提供一个默认的
5 如果自定义了析构函数,系统只会调用自定义的析构函数
6 用户无需主动调用析构函数,在对象的生命周期结束时,系统会自动调用
析构函数
7 用户可以主动调用析构函数,但是只是执行了函数体,不是真正释放内存,
只有当对象的声明周期结束时,才释放内存(建议不要显示调用)
8 如果对象在栈中存放,先构造的后析构
9 如果对象在堆中存放,delete时调用析构函数
10 如果在构造函数或其他函数中使用new申请了空间,就需要在析构函数中
用delete释放空间。
多个对象的构造和析构顺序:构造顺序和对象的定义顺序相同;
析构顺序和定义顺序相反(先构造的后析构)
代码示例:
#include
using namespace std;
class demo
{
public:
demo(int val=0)
{
ival=val;
cout<<"demo(int val=0)------\r\n";
}
void getint()
{
cout<<"getint:ival="<
为什么在c++中不使用malloc和free,而要使用new和delete呢?
1 new/delete是运算符,不需要加头文件;malloc/free是函数,需要加头文件
《stdlib.h》
2 malloc的返回值是void*型指针,需要强转才能使用;new的返回值是特定的
数据类型指针,不要强转。
3 new申请内存时已经确定了内存中存放的数据类型,new会做类型检查,即指
针的数据类型要和new后边的数据类型保持一致
4 Malloc申请内存大小需要手动计算,new只需要确定元素的个数和数据类型
5 free的入参是内存的首地址,delete内存时,后边跟指针或[]指针
delete p 或delete[] p;
6 new一个对象时会自动调用该对象的构造函数,delete 一个对象时会自动调
用该类的析构函数。而malloc/free没有这个功能。
3.1static关键字
static用来修饰类中的成员变量和成员函数,被修饰的成员变量称为静态成员变量;被修饰的成员函数称为静态成员函数。
(静态成员属于整个类,由该类的所有对象共享使用)
3.1.1静态成员变量
定义:static修饰的成员变量就是静态成员变量
特点:1) 静态成员变量属于整个类,由该类的所有对象共享访问。
2 ) 静态成员变量存贮在全局数据区,在定义时分配空间,所以只能在
类体外、主函数外定义,定义时需要加上类名这个作用域
3.1.2静态成员函数
定义:static修饰的成员函数就是静态成员函数
特点:1) 静态成员函数没有this指针(this指针指向当前对象的首地址,
静态成员函数属于整个类,不属于某个对象,所有没有this指针)
2) 静态成员函数可以通过两种方式访问:1 通过对象名.函数的方式访问
2 类名::函数()
总结:1 非静态成员函数可以访问静态成员变量和非静态成员变量
2 静态成员函数只能访问静态成员变量,不能访问非静态成员变量
代码示例:
#include
using namespace std;
class demo
{
public:
demo(int a=0);
static void getint();//声明静态成员函数
static void getint1();
static int ival;//声明静态成员变量
int num;
};
demo::demo(int a)
{
ival=a;
cout<<"demo(int a)------------\r\n";
}
void demo::getint()
{
// getint1();
cout<<"ival="<
3.2const关键字
const修饰的目标受到C++类型安全机制的强制保护,防止被意外修改
3.2.1const成员变量
定义:被const修饰的类的成员变量称为常成员变量
特点:常成员变量只能通过初始化列表的方式初始化,而且一旦初始化,其值不能被修改
3.2.2const成员函数
定义:被const修饰的类的成员函数称为常成员函数
特点:1 const修饰成员函数,const放在函数的后边,并且定义时也需要加上const
2 const成员函数不能修改任何成员变量的值
3.2.3const对象
const 修饰的对象称为常对象,常对象只能调用常成员函数,不能调用非常成员函数
const demo obj;
3.2.4const引用
const 修饰的对象引用称为常引用,常引用只能调用常成员函数,不能调用非常成员函数
3.2.5const对象指针
const 修饰的对象指针称为常对象指针,常对象指针只能调用常成员函数,不能调用非常成员函数
代码示例:
#include
using namespace std;
class demo
{
public:
demo(int val=0);
void getint() const;
void getint1();
private:
int ival;
};
demo::demo(int val)
{
ival=val;
cout<<"demo(int val)--------\r\n";
}
void demo::getint() const
{
cout<<"getint():ival="<getint();
// p->getint1();//error,常对象指针不能调用非常成员函数
return 0;
}
3.3mutable关键字
作用:用来修饰成员变量,使成员变量不受const的约束(const成员函数和const对象都能修改成员变量的值)
代码示例:
#include
using namespace std;
class demo
{
public:
demo(int val=0);
void getint() const;
mutable int ival;
};
demo::demo(int val)
{
ival=val;
cout<<"demo(int val)--------\r\n";
}
void demo::getint() const
{
ival=300;//常成员函数可以修改被mutable修饰的成员变量的值
cout<<"getint():ival="<
4.1 定义:
友元是类的好朋友,一个类主动声明另一个类或函数是它的朋友,那么就给另外 一个类或函数提供了访问本类私有成员的权限。
友元的种类:1 友元函数(友元外部函数、友元成员函数)2 友元类
4.2友元外部函数
定义:是类外部的函数,没有this指针,该友元函数可以访问封装于本类中的私有成员。
如何声明外部函数是当前类的友元函数?
在类体中声明,用friend关键字声明。friend void func();
代码示例:
#include
using namespace std;
class B;
class A
{
public:
A(int val=0);
private:
friend class B;
int ival;
};
class B
{
public:
void func(A &obj);
void func1(A &obj,int val);
};
A::A(int val)
{
ival=val;
cout<<"A(int val)---------\r\n";
}
void B::func(A &obj)
{
cout<<"func():ival="<
4.3友元成员函数
定义:另外一个类中的某个成员函数被声明没当前了的友元,该成员函数可以访问
当前类对象的私有成员。
如何声明另外一个类中的某个成员函数是当前类的友元函数?
在当前类体中,用friend声明,friend void A::func();
例如:若A类的某个成员函数是B类的友元,只有这个成员函数可以访问B类的私有
成员
注意:1 A类必须定义在B类之前,
2 B类需要在A类之前声明,
3 A类中的友元函数必须定义在A类的外部,而且要在B类定义之后。
代码示例:
#include
using namespace std;
class demo
{
public:
demo(int val=0)
{
ival=val;
cout<<"demo(int val)-----------\r\n";
}
void getint()
{
cout<<"getint():ival="<
4.4友元类
定义:声明另外一个类是当前类的友元,另外一个类的所有成员函数都可以访问
当前类对象的私有成员
如何声明另外一个类是当前类的友元?
在当前类中用friend声明:friend class B;
例如:若B类为A类的友元类,则B类的所有成员函数都是A类的友元函数,都可以
访问A类中的私有成员
总结:友元关系是单向的
友元关系是不能传递的
友元关系是不能被赋值的,是声明而来的
注意:友元破坏了类的封装性,使用需谨慎时
代码示例:
#include
using namespace std;
class B;
class A
{
public:
void setint();
void getint();
void getint1(B &obj);
};
class B
{
public:
B(int val=0);
private:
friend void A::getint();//声明友元成员函数
friend void A::getint1(B &obj);
static int ival;
};
void A::setint()
{
//cout<<"setint():B::ival="<
PS:不足或者不正确的地方还请大家多多指正批评!