要求:设计一个圆形类和一个点类,计算点在圆外还是圆内还是圆上,求点和圆的关系
//circle.cpp
#include"circle.h"
#include
void Dit::set(int x, int y)
{
m_x = x;
m_y = y;
}
int Dit::getx()
{
return m_x;
}
int Dit::gety()
{
return m_y;
}
double Dit::Distance(Dit d)
{
double s;
s = sqrt((d.m_x - m_x)*(d.m_x - m_x) + (d.m_y-m_y)*(d.m_y-m_y));
cout << "d.m_x = " << d.m_x << "d.m_y = " << d.m_y<<"m_x= "<< m_x<<"m_y= "<< m_y <<endl;
cout << "两点之间的距离是:" << s << endl;
return s;
}
void Circle::set(int x, int y, int r)
{
m_d.set(x ,y);
m_r = r;
}
void Circle::Relationship(Dit d)
{
double distance = d.Distance(m_d);
if(distance == m_r)
{
cout<< "点在圆上" << endl;
}
else if(distance > m_r)
{
cout << "点在圆外" << endl;
}
else
{
cout << "点在园内" << endl;
}
}
//circle.h
#ifndef _H_CIRCLE_
#define _H_CIRCLE_
#include
using namespace std;
class Dit
{
private:
int m_x;
int m_y;
public:
double Distance(Dit d);
void set(int x, int y);
int getx();
int gety();
};
class Circle
{
private:
Dit m_d;
int m_r;
public:
void set(int x, int y, int r);
void Relationship(Dit d);
};
#endif
#include"circle.h"
int main()
{
int d_x = 1;
int d_y = 1;
Dit d;
Circle c;
d.set(1, 1);
c.set(3, 4, 5);
c.Relationship(d);
return 0;
}
在C++中,有一种特殊的成员函数,它的名字和类名相同,没有返回值,不需要用户显示调用(也不能调用),而且在创建对象的时候自动执行。这种特殊的成员函数称为构造函数
几点说明:
1.构造函数的函数名和类名必须相同
2.构造函数不能有返回值,函数体内不能有return语句
3.构造函数在定义对象时会自动调用,不需要手动调用
#include
using namespace std;
class Array
{
private:
int *data; //数组的起始地址
int size; //数组的大小
public:
Array(); //无参构造函数,函数名和类名相同,没有返回值,完成对象的初始化操作
void SetVal(int index,int val);
int GetVal(int index);
~Array(); //析构函数,函数名是:类名+~,没有返回值
};
Array::Array()
{
cout<<"array的无参构造函数"<<endl;
size = 5;
data = (int *)malloc(sizeof(int)*size);
}
void Array::SetVal(int index,int val)
{
data[index] = val;
}
int Array::GetVal(int index)
{
return data[index];
}
Array::~Array() //析构函数,函数名是:类名+~,没有返回值
{
cout<<"Array的析构函数"<<endl;
if(NULL != data)
{
free(data);
data = NULL;
}
}
int main()
{
Array a1; //创建对象时自动调用构造函数
for(int i = 0; i < 5; i++)
{
a1.SetVal(i,i+1);
}
for(int i = 0;i<5;i++)
{
cout << a1.GetVal(i) << "" <<endl;
}
return 0;
}
输出为:
array的无参构造函数
1 2 3 4 5
Array的析构函数
和普通函数一样,构造函数时允许重载的,一个类可以有多个重载的构造函数,在创建对象时根据传递的实参去决定调用哪个构造函数。
#include
using namespace std;
class Array
{
private:
int *data; //数组的起始地址
int size; //数组的大小
public:
Array(); //无参构造函数,函数名和类名相同,没有返回值,完成对象的初始化操作
Array(int s); //有参构造函数
Array(int s, int z); //有两个参数的构造函数
void SetVal(int index,int val);
int GetVal(int index);
~Array(); //析构函数,函数名是:类名+~,没有返回值
};
Array::Array()
{
cout<<"array的无参构造函数"<<endl;
size = 5;
data = (int *)malloc(sizeof(int)*size);
}
Array::Array(int s)
{
size = s;
data = (int *)malloc(sizeof(int)*size);
cout <<"Array的有参构造函数, size = " << size <<endl;
}
Array::Array(int s, int z)
{
size = s;
data = (int *)malloc(sizeof(int)*size);
cout <<"Array的两个参数的构造函数, size= "<< size << endl;
}
void Array::SetVal(int index,int val)
{
data[index] = val;
}
int Array::GetVal(int index)
{
return data[index];
}
Array::~Array() //析构函数,函数名是:类名+~,没有返回值
{
cout<<"Array的析构函数"<<endl;
if(NULL != data)
{
free(data);
data = NULL;
}
}
int main()
{
/*
Array a1; //创建对象时自动调用构造函数
for(int i = 0; i < 5; i++)
{
a1.SetVal(i,i+1);
}
for(int i = 0;i<5;i++)
{
cout << a1.GetVal(i) << "" <
Array a2(6);//初始化方式为括号法
Array a3(7,8);
Array a4 = 100;//初始化方法为等号法,有局限,只能有一个参数
return 0;
}
运行结果:
Array的有参构造函数, size = 6
Array的两个参数的构造函数, size= 7
Array的有参构造函数, size = 100
Array的析构函数
Array的析构函数
Array的析构函数
1.概念
格式:className(const className &obj)
拷贝构造函数也称为赋值拷贝构造函数
作用:用一个已有的对象去初始化另一个对象
Array::Array(const Array &a)
{
cout<<"Array的拷贝构造函数"<<endl;
}
2.拷贝构造函数调用的时机
1)用一个对象初始化另一个对象
Array a5 = a4;
Array a6(a4);
Array a7 = Array(a4);
2)当函数的形参是一个对象时,比如:
void print(Array a)
{
a.GetVal(1);
}
Array a1;
print(a1);
输出结果为:
Array的有参构造函数, size = 100
Array的拷贝构造函数
Array的析构函数
Array的析构函数
注意:这里,我在有参的构造函数中,给data指针分配了内存,在析构中free了内存,所以当我们在拷贝构造函数中没有给指针分配内存时,那么这个指针的内存会被释放两次,那么就会发生crash,这一点后面会讲到。这里没有crash是因为我将析构函数中的free函数注释了
3)函数返回值是一个对象
Array& Func()
{
Array a1;
return a1;
}
Array a2 = Func();
首先会调用无参构造函数,因为Func中创建了a1对象,将a1 return时,会产生匿名对象(没有名字的对象),因为这时候a1被释放了(因为a1是局部的),那么这时候用这个a1匿名对象初始化a2,就会调用匿名对象的拷贝构造函数,编译器实际上不会给a2分配空间,而是将匿名对象给了a2,直接用a2给这个匿名对象命名,所以不会产生两次拷贝构造。
#include
using namespace std;
class Array
{
private:
int *data;
int size;
public:
Array(int s)
{
cout <<"array的有参构造函数"<<endl;
size = s;
data = (int *)malloc(sizeof(int)*size);
}
~Array()
{
cout <<"array的析构函数"<<endl;
if(data != NULL)
{
free(data);
data = NULL;
}
}
Array(Array &a)//深拷贝构造函数
{
cout <<"array的深拷贝构造函数"<< endl;
size = a.size;
data = (int*)malloc(sizeof(int)*size);//和浅拷贝的区别在于,重新给指针分配了空间,用于保存数组中的值。不会和被拷贝的数组同用一片空间
for(int i = 0; i < size; i++)
{
data[i] = a.data[i];
}
}
};
int main()
{
Array a1(10);
Array a2(a1);
return 0;
输出:
array的有参构造函数
array的深拷贝构造函数
array的析构函数
array的析构函数
}
#include
using namespace std;
class Test
{
public:
Test()
{
cout <<"Test 的无参构造函数"<<endl;
}
Test(int a)
{
cout <<"Test 的一个参数构造函数"<<endl;
}
Test(const Test &a)
{
cout <<"Test 的拷贝构造函数"<<endl;
}
};
int main()
{
Test t1;//编译器会默认提供无参构造函数
Test t2(t1);//编译器会提供默认的拷贝构造函数(浅拷贝)
Test t3;//一旦提供了无参构造函数,编译器就不再提供无参构造函数
Test t4;//一旦提供了有参的构造函数,编译器不会再提供默认的无参构造函数
Test t5;//一旦提供了拷贝构造函数,编译器也不会再提供默认的无参构造函数
return 0;
}
1). 格式: ~Array()析构函数
2). 概念:
当一个对象销毁时,系统会自动调用一个函数来进行清理工作,如释放内存,关闭打开的文件,这个函数就是析构函数。
析构函数没有参数,不能被重载,一个类中只能有一个析构函数,如果用户没有提供析构函数,编译器会自动生成一个默认的析构函数。
#include
using namespace std;
class Test
{
public:
Test()
{
cout <<"Test 的无参构造函数"<<endl;
}
Test(int a)
{
cout <<"Test 的一个参数构造函数"<<endl;
}
Test(const Test &a)
{
cout <<"Test 的拷贝构造函数"<<endl;
}
~Test()
{
cout<<"test的析构函数"<<endl;
}
};
int main()
{
Test(); //匿名对象,本行代码执行完毕,立即被释放,也就是立即调用析构函数
cout<<"*************"<<endl;
return 0;
}
#include
using namespace std;
class Test
{
public:
Test()
{
cout <<"Test 的无参构造函数"<<endl;
}
Test(int a)
{
cout <<"Test 的一个参数构造函数"<<endl;
}
Test(const Test &a)
{
cout <<"Test 的拷贝构造函数"<<endl;
}
~Test()
{
cout<<"test的析构函数"<<endl;
}
};
int main()
{
//Test t1; 栈空间创建对象
//c++中不用malloc,是因为其不会自动调用构造函数和析构函数
Test *pt = (Test *)malloc(sizeof(Test));//在堆空间申请一个对象大小的内存
if(NULL == pt)
{
cout << "malloc is failed" <<endl;
}
free(pt);
pt = NULL;
Test *pt2 = new Test; //在堆中申请内存,并且自动调用构造函数
delete pt2; //自动调用析构函数
pt2 = NULL;
int *p2 = new int;//给整形分配空间
delete p3;
p3 = NULL;
char *p3 = new char;//给一个字符申请空间
delete p3;
p3 = NULL;
char *p4 = new char[10]; //给10个字符申请空间
detele []p4;
p4 = NULL;
Test *t2 = new Test(1);//给一个Test对象申请空间,并且初始化
delete t2;
t2 = NULL;
Test *t3 = new Test[5]{1,2,3,4,5};//申请十个Test类对象,并初始化
return 0;
}
1.malloc是函数,new是关键字
2.malloc的返回值类型是void*, new是申请空间的类型
3.malloc不能初始化空间,new可以初始化
4.malloc不能自动调用构造函数,new可以
#include
using namespace std;
class Date
{
private:
int m_year;
int m_month;
int m_day;
public:
/* Date()
{
cout<<"data的无参构造函数"<
Date(int y, int m, int d)
{
cout << "data的有参构造函数"<< endl;
m_year = y;
m_month = m;
m_day = d;
}
~Date()
{
cout <<"data的析构函数"<< endl;
}
};
calss Test
{
private:
Test(int s)
{
cout << "Test的构造函数"<< endl;
}
}
//对象的初始化列表:1.当类对象作为成员变量,并且该类没有提供无参构造函数时,我们需要使用初始化列表 2.成员变量用const修饰(初始化和赋值不同)也只能使用初始化列表
class Student
{
private:
const int id;
Date birth;
Tets t1;
public:
Student(int i, int y, int m, int d):t1(10),birth(y,m,d),id(i)
{
cout<<"student 有参构造函数"<<endl;
}
};
int main()
{
Student s1(100,1996,2,28);
return 0;
}
几点说明:
1、初始化列表优先于当前对象的构造函数先执行
2、子对象(就是上面代码中的Data成员对象)的初始化顺序和其在初始化列表的排序无关,但和在类中声明的顺序有关,先声明的先初始化。所以先初始化Data,然后是Test,最后是Student。
3、析构函数的调用顺序,和构造函数正好相反
4、参数的初始化列表有一个很重要的作用,那就是初始化const的成员变量