C++基础知识补充
c++中创建对象不需要用new
比如Cube c1;
此时就声明了一个Cube对象
c++中,this关键字是指指向当前对象的指针
#include <iostream>
using namespace std;
class Student{
public:
void setname(char *name);
void setage(int age);
void setscore(float score);
void show();
private:
char *name;
int age;
float score;
};
void Student::setname(char *name){
this->name = name;
}
void Student::setage(int age){
this->age = age;
}
void Student::setscore(float score){
this->score = score;
}
void Student::show(){
cout<<this->name<<"的年龄是"<<this->age<<",成绩是"<<this->score<<endl;
}
int main(){
Student *pstu = new Student;
pstu -> setname("李华");
pstu -> setage(16);
pstu -> setscore(96.5);
pstu -> show();
return 0;
}
如果获取了一个对象指针,那么可以用该对象->成员变量来使用该成员变量,该对象->方法来调用其方法
如果获取了一个对象引用,那么可以用该对象.成员变量来使用成员变量,或者该对象.方法来调用其方法
函数中既可以传形参,也可以传指针,也可以传引用
传引用的话,基础数据类型,和平时的用法一样,对于对象来说,用点.来调用其方法和变量
传指针的话,基础数据类型,需要解引用,对于对象来说,需要用->来调用其方法和变量
#include <iostream>
using namespace std;
#include <string>
//点类
class Point
{
public:
//设置X坐标
void setX(int x)
{
m_x = x;
}
//获取X坐标
int getX()
{
return m_x;
}
//设置Y坐标
void setY(int y)
{
m_y = y;
}
//获取Y坐标
int getY()
{
return m_y;
}
private:
int m_x;
int m_y;
};
//设置一个圆类Circle
class Circle
{
public:
//设置半径
void setR(int r)
{
m_R = r;
}
//获取半径
int getR()
{
return m_R;
}
//设置圆心
void setCenter(Point center)
{
m_center = center;
}
//获取圆心
Point getCenter() //m_center是Piont类的数据
{
return m_center;
}
private:
int m_R;
//在类中可以让另一个类 作为本类中的成员--与结构体相似
Point m_center;
};
//判断点和圆的关系
void isInCircle(Circle& c, Point& p)
{
if ((p.getX() - c.getCenter().getX()) * (p.getX() - c.getCenter().getX()) + (p.getY() - c.getCenter().getY()) * (p.getY() - c.getCenter().getY()) == c.getR() * c.getR())
cout << "点在圆上" << endl;
else if ((p.getX() - c.getCenter().getX()) * (p.getX() - c.getCenter().getX()) + (p.getY() - c.getCenter().getY()) * (p.getY() - c.getCenter().getY()) > c.getR() * c.getR())
cout << "点在圆外" << endl;
else
cout << "点在圆内" << endl;
}
int main()
{
//创建并设置点P1
Point P1;
P1.setX(10);
P1.setY(9);
//创建并设置点P2--圆心
Point P2;
P2.setX(10);
P2.setY(0);
//设置圆C1
Circle C1;
C1.setR(10);
C1.setCenter(P2);
isInCircle(C1, P1);
system("pause");
return 0;
}
构造函数和析构函数
如果我们不写构造函数和析构函数,那么编译器会给我们提供构造函数和析构函数,但是编译器的构造函数和析构函数是空实现
构造函数和析构函数,构造函数是当对象实例化的时候调用的
析构函数是是对象销毁时自动调用,而且只会调用一次
构造函数和析构函数都是没有返回值的
构造函数和析构函数的函数名都是类名 比如构造函数是Person(),析构函数是~Person()
在main函数中,对象是放在堆区的,需要我们手动释放
按参数分为,构造函数中有无参构造和有参构造
按类型分为,构造函数中有普通构造和拷贝构造
拷贝构造函数,拷贝构造函数是将另一个对象的属性全部拷贝到自己身上
拷贝构造函数就是把另一个对象原封不动的赋值给自己
class MyClass {
public:
int data;
// 默认构造函数
MyClass() {
data = 0;
}
// 拷贝构造函数
MyClass(const MyClass& other) {
//不能修改另一个类,所以用const
data = other.data;
}
};
c++中,对象实例化,一般不用new,记住
Person p1;//默认构造,不要加括号,如果加了括号,编译器会认为是函数声明,比如Person p1(),编译器会认为这是一个函数
Person p2(10);//有参构造
Person p3(p2);//拷贝构造
在C++中,new和malloc都是用指针来接收的,如Person *p1=new Person();
java中没有析构函数,java中有一个GC垃圾回收器,而C++中,所有的堆区内存都需要我们手动释放
在java中,没有指针,所有都是引用,所有对象的方法和属性都可以用点.来调用
当我们用delete来销毁对象时,会直接调用析构函数,从而清除对象
//此时声明了一个匿名对象,当程序结束后,系统会立即回收匿名对象 Person(10) Person p1; Person p2=Person(10); //不用new,这点跟java不同 Person p3=Person(p2);
java里只有两种构造函数,无参构造和有参构造,没有什么拷贝构造
对于普通类型,用delete来释放,对于数组类型,用delete[] 来释放,如delete[] arr
代码举例二:有new和delete
#include<iostream>
using namespace std;
class A
{
public:
A()
{
cout<<"构造函数"<<endl;
}
~A()
{
cout<<"析构函数"<<endl;
}
};
int main()
{
A a;//创建了A的对象a,调用无参的构造函数,输出第一行的“构造函数”
A * p;
p=new A();//new A在堆中分配对象,同时调用无参的构造函数, 输出第二行的“构造函数”
delete p;//删除p指向的空间,也就是释放这个对象,必然要调用析构函数,输出第三行的“析构函数”
cout<<"end of main"<<endl;
return 0;
}
比如A函数,B函数中有某一个功能
有一个C函数,需要调用A函数,或者B函数,那么此时就可以用函数指针的形式
#include <iostream>
#include <string>
using namespace std;
string base {"hello world"};
string append(string s)
{
return base.append(" ").append(s);
}
string prepend(string s)
{
return s.append(" ").append(base);
}
string combine(string s, string(*g)(string a))
{
return (*g)(s);
}
int main()
{
cout << combine("from MSVC", append) << "\n";
cout << combine("Good morning and", prepend) << "\n";
}
C++的构造函数分为三类:有参,无参,拷贝
C++中有三种编译器提供的构造函数和析构函数:
1.默认无参构造函数(空实现)
2.默认析构函数(空实现)
3.默认拷贝构造函数
如果已经定义了有参构造,那么编译器就不会再提供无参构造,但是会提供拷贝构造
如果用户定义拷贝构造函数,那么默认的有参,无参都没有了
数据类型分为基本数据类型和引用数据类型
深拷贝和浅拷贝的区别:
深拷贝和浅拷贝的区别就是对于堆区分配的数据,深拷贝会新申请一片空间,然后拷贝这些值
浅拷贝只会拷贝这个引用的地址
默认的拷贝构造函数都是浅拷贝
一般对于对象,都是用new和delete,malloc和free是C语言中的用法,C语言没有面向对象的概念,C++中有面向对象的概念,当使用new时,会调用构造函数,当使用delete时,会调用析构函数
#include <iostream>
#include <string>
using namespace std;
class Cperson
{
public:
Cperson()
{
pp = new int;
cout << "Beginning" << endl;
}
~Cperson()
{
delete pp;
cout << "End" << endl;
}
private:
int *pp;
};
int main()
{
Cperson *op1 = (Cperson *)malloc(sizeof(Cperson));
free(op1);
Cperson *op2 = new Cperson;
delete op2;
system("pause");
return 0;
}
这个对象里,堆区的内容都要用析构函数释放,也就是所有的指针型数据类型
浅拷贝会带来一个问题,如果Person p1对象中有a*指针变量,Person p2(p1),如果采用默认拷贝构造函数,那么会把a*指针变量浅拷贝一遍,如果执行析构函数,对p1和p2均进行释放,由于指向了同一片内存空间,可能会出现double free这种现象
如果对象中有堆区的空间,也就是指针型空间,那么必须自己提供拷贝构造函数

