class People {
double height;//身高
char sex;//性别
int age;//年龄
string name;//姓名
void run() {//跑
cout << "I can run" << endl;
}
void speak() {//说话
cout << "I can speak" << endl;
}
};
#include<iostream>
using namespace std;
class People {
public :
int age;
void speak() {
cout << "my age is "<< age << endl;
return ;
}
};
int main() {
People a;
a.age = -100;
a.speak();
return 0;
}
#include<iostream>
using namespace std;
class People {
public :
void speak() {
cout << "my age is "<< age << endl;
return ;
}
void set_age(int x) {
if (age <= 0 || age > 1000) {
perror("your age is error\n");
exit(1);
}
age = x;
return ;
}
int get_age() {
return age;
}
private :
int age;
};
int main() {
People a;
a.set_age(-100);
a.speak();
return 0;
}
构造函数和析构函数
定义一个对象的流程:
对于构造函数的详细解析如下代码:
cpp复制代码
#include<iostream>
using namespace std;
class A {
public :
A() {//默认构造函数
cout << "default constructor" << endl;
}
//如果这里没有const关键字,传入的对象是const声明的那么就会报错
//如果没有&(引用),那么将会造成无限套娃的拷贝构造
//假如这里没有&,那么这里的形参就相当于实参给他赋值
//而赋值就是 A a = b, b是实参传入的值
//那这里就会又调用构造函数,形成无限套娃
A(const A &a) {
this->x = a.x;
this->y = a.y;
cout << "copy constructor" << endl;
}
A(int x, int y) {//有参构造函数
cout << "have parameter constructor" << endl;
this->x = x;//this表示当前对象的地址
this->y = y;
}
void operator=(const A &a) {//这个函数是=运算符重载,是类中默认有的
cout << "this is assigment" << endl;
return ;
}
A(int x) {//转换构造函数
cout << "conversion constructor" << endl;
this->x = x;
this->y = 0;
}
void output() {
cout << "(" << x << ", " << y << ")" << endl;
}
~A() {//析构函数
cout << "destructor" << endl;
}
private :
int x, y;
};
void func(A a) {
cout << "func : ";
a.output();
return ;
}
int main() {
A a;//调用默认构造函数
cout << "1-------------------------" << endl;
A b(1, 2);//调用有参构造
cout << "2-------------------------" << endl;
//这里就调用了拷贝构造函数
A e = b;
cout << "3-------------------------" << endl;
//这里只是运用了普通赋值运算符
//通过执行会发现没有执行任何构造函数
a = b;
cout << "4-------------------------" << endl;
//调用转换构造,将int类型转换为A类型
//这里也可以是另一个类型的对象,那也是转换构造
//不过还需要从新定义一个需要转换构造的函数,里面的参数就是对应的类型
A c(3);
cout << "5-------------------------" << endl;
//这里调用的是拷贝构造函数,将对象b进行拷贝给函数形参a
func(b);
func(c);
cout << "6-------------------------" << endl;
//对于这中函数调用情况
//这里就会用到转换构造
//他会隐式的将int类型5通过转换构造转会为A类型
func(5);
cout << "7-------------------------" << endl;
//这里相当于A d(4);
//这里可以这样理解
//等号类型相同编程才能通过
//那么4,int类型就会通过转换构造变成A类型
//如果没有转换构造那么就编译无法通过
A d = 4;
a = 6;
cout << "8-------------------------" << endl;
return 0;
}
构造函数的初始化列表
构造函数中的初始列表使用:
cpp复制代码
#include<iostream>
using namespace std;
class C {
public:
C(int n) {
this->num = n;
cout << "C coversion constructor" << endl;
}
void output() {
cout << num;
}
private :
int num;
};
class A {
public :
//:后面是构造函数的初始化列表
A(int a) : a(a), b(10), c(6) {
cout << "A constructor" << endl;
}
void output() {
cout << " " <<a << " " << b << " ";
c.output();
cout << endl;
return ;
}
private :
int a, b;
C c;
};
int main() {
A a(2);
a.output();
return 0;
}
构造函数和析构函数的调用顺序
如下这份代码:
cpp复制代码
#include <iostream>
#include <string>
using namespace std;
class A {
public :
A() {};
A(string n) {
name = n;
cout << name << " class A construtor" << endl;
}
~A() {
cout << name << " class A destructor" << endl;
}
int *p;
private :
string name;
};
class B {
public :
//:a(a)
//:后面是构造函数时,最该对象中的成员属性进行初始化操作
B(string n, A &a) : a(a){
name = n;
cout << name << " class B construtor" << endl;
//new关键字可以理解为,C语言中malloc去堆区中开辟一段空间
a.p = new int[10];
return ;
}
A &a;//创建一个引用属性,这里&a可以暂时理解为取a的地址
~B() {
//delete就相当于C语言中的free对开辟空间的释放
delete a.p;
cout << name << " class B destructor" << endl;
}
private :
string name;
};
int main() {
A a("a");
B b("b", a);
return 0;
}
#include<iostream>
using namespace std;
//在类中只放方法的声明
class Point {
public :
Point();
Point(int x, int y);
void set_x (int x);
void set_y (int y);
int get_x() const;
int get_y() const;
static int x_cnt();
private :
static int get_x_cnt;
int x, y;
};
//对于类中的方法进行实现
//那么就可以将这两部分拆开
//定义放在源文件中,声明放在头文件中
Point::Point() : x(0), y(0) {}
Point::Point(int x, int y) : x(x), y(y) {}
void Point::set_x(int x) {
this->x = x;
}
void Point::set_y(int y) {
this->y = y;
}
int Point::get_x() const{
Point::get_x_cnt += 1;
return x;
}
int Point::get_y() const{
return y;
}
int Point::x_cnt() {
return Point::get_x_cnt;
}
int Point::get_x_cnt = 0;
int main() {
Point p1(3, 4), p2(5, 6);
cout << p1.get_x() << ", " << p1.get_y() << endl;
cout << p2.get_x() << ", " << p2.get_y() << endl;
p1.get_x();
p1.get_x();
p1.get_x();
cout << "x_cnt : " << Point::x_cnt() << endl;
return 0;
}
default和delete关键字
delete和default关键字引用代码:
cpp复制代码
#include<iostream>
using namespace std;
class A {
public :
//A() = delete;
A() {
cout << "default constructor" << endl;
}
A(int n) : x(n) {
cout << "conversion constructor" << endl;
}
A(const A &) {
cout << "copy constructor" << endl;
}
private :
int x;
};
class B {
public :
B() = default;
B(const B&) = default;
private :
A a1, a2, a3;
};
class C {
public :
C() = default;
//C(const C&) {}//这种情况叫撒比构造
C(const C&) = default;
private :
A a1, a2, a3;
};
class Point {
public :
Point() = default;//请求编译器生成默认构造函数
Point(int x, int y) : x(x), y(y) , p(new int(5)), a(1){}
//Point(const Point &) = delete;//删除编译器的拷贝构造函数
//Point(const Point &) = default;//拷贝函数生成默认行为,在使用这个拷贝构造函数时就会造成双重释放的报错
//这就是深拷贝
Point(const Point &a) : x(a.x + 1), y(a.y + 2), a(a.a){
//如果这里成员属性a直接用这样去赋值拷贝
//那么成员属性a就会使用A类的默认构造函数进行构造
//而A类的默认构造函数已经被删除了,那么就会报错
//this->a = a.a;
this->p = new int;
*(this->p) = *(a.p);
}
~Point() {
delete p;
}
private :
A a;
int *p;
int x, y;
};
int main() {
Point p1(1, 2), p2 = p1;
return 0;
}
对象和引用
代码演示:
cpp复制代码
#include<iostream>
using namespace std;
class A {
public :
A() = default;
A(const A&) = default;
private :
};
class B {
public :
B(A &a) : a(a) {}
private :
A &a;
};
class C {
public :
C() = default;
C(const C &) = default;
static void destroy(C *c) {
delete c;
return ;
}
private :
~C() {}
};
int main() {
A a;
B b(a);
C *c = new C();
C::destroy(c);
return 0;
}
返回值优化
先回顾一下一个对象是如何进行创建的:
如下代码:
cpp复制代码
#include<iostream>
using namespace std;
class A {
public :
A() {
cout << this << " default constructor" << endl;
}
A(const A &) {
cout << this << " copy constructor" << endl;
}
string s;
};
A func() {
//这里创建temp调用了默认构造
A temp;
cout << "temp = " << &temp << endl;
temp.s = "hello func";
//return这里会有一个匿名对象
//然后temp会通过拷贝构造拷贝给这个匿名对象
return temp;
}
int main() {
//然后这里的a通过拷贝构造,拷贝这个匿名对象
//那么创建a对象最终会调用
//一次默认构造,两次拷贝构造对吧
A a = func();
cout << "a = " << &a << endl;
return 0;
}