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这种现象
如果对象中有堆区的空间,也就是指针型空间,那么必须自己提供拷贝构造函数