实际上,类就是对象的类型,对象也是一种变量,因此你能够在堆中建立int型变量,天然也就能建立自定义型变量。ios
Cat *pCat = new Cat;c++
这将调用默认构造函数(无参构造函数),每当在堆或栈中建立对象时,都将调用构造函数。ide
对指向堆中对象的指针调用delete时,将调用对象的析构函数,而后释放内存。函数
程序清单11.1 HeapCreator.cppthis
#include <iostream> class SimpleCat { public: SimpleCat() { std::cout << "Constructor called\n"; itsAge = 1; } ~SimpleCat() { std::cout << "Destructor called\n"; } private: int itsAge; }; int main() { std::cout << "SimpleCat simpleCat ...\n"; SimpleCat simpleCat; std::cout << "SimpleCat *pRags = new SimpleCat ...\n"; SimpleCat *pRags = new SimpleCat; std::cout << "delete pRags ...\n"; delete pRags; std::cout << "Exiting, watch simpleCat go ...\n"; return 0; }
这里最后一个Destructor called是由于main()函数结束时,simpleCat对象再也不在做用域中,因此编译器调用其析构函数。3d
方法一(解引用运算符):指针
(*pRags).getAge();
方法二(指向运算符->):code
pRags->getAge();
程序清单11.2 HeapAccessor.cpp对象
#include <iostream> class SimpleCat { public: SimpleCat() { itsAge = 2; } ~SimpleCat() { std::cout << "Destructor called\n"; } int getAge() const { return itsAge; } void setAge(int age) { itsAge = age; } private: int itsAge; }; int main() { SimpleCat *simpleCat = new SimpleCat; std::cout << "simpleCat is " << (*simpleCat).getAge() << " years old" << "\n"; simpleCat->setAge(5); std::cout << "simpleCat is " << simpleCat->getAge() << " years old" << "\n"; return 0; }
类可能有一个或多个数据成员为指针,并指向堆中的对象。可在构造函数或成员函数中分配内存,并在析构函数中释放内存。blog
程序清单11.3 DataMember.cpp
#include <iostream> class SimpleCat { public: SimpleCat() { itsAge = new int(2); itsWeight = new int(5); } ~SimpleCat() { delete itsAge; delete itsWeight; } int getAge() const { return *itsAge; } void setAge(int age) { *itsAge = age; } int getWeight() const { return *itsWeight; } void setWeight(int weight) { *itsWeight = weight; } private: int *itsAge; int *itsWeight; }; int main() { SimpleCat *simpleCat = new SimpleCat; std::cout << "simpleCat is " << simpleCat->getAge() << " years old" << "\n"; simpleCat->setAge(5); std::cout << "simpleCat is " << simpleCat->getAge() << " years old" << "\n"; return 0; }
每一个类成员函数都有一个隐藏的参数——this指针,它指向用于调用函数的对象。
一般,在成员函数中,无需使用this指针来访问当前对象的成员变量,若是愿意,能够显示地使用this指针。
程序清单11.4 This.cpp
#include <iostream> class Rectangle { private: int itsLength; int itsWidth; public: Rectangle(); ~Rectangle(); void setLength(int length) { this->itsLength = length; } int getLength() const { return this->itsLength; } void setWidth(int width) { this->itsWidth = width; } int getWidth() const { return this->itsWidth; } }; Rectangle::Rectangle() { itsWidth = 5; itsLength = 10; } Rectangle::~Rectangle() { } int main() { Rectangle theRect; std::cout << "theRect is " << theRect.getLength() << " feet long." << std::endl; std::cout << "theRect is " << theRect.getWidth() << " feet wide." << std::endl; theRect.setLength(20); theRect.setWidth(10); std::cout << "theRect is " << theRect.getLength() << " feet long." << std::endl; std::cout << "theRect is " << theRect.getWidth() << " feet wide." << std::endl; return 0; }
悬垂指针又称为野指针或者迷失指针,指的是对指针调用了delete(释放其指向的内存)以后,没有从新赋值(即没有从新初始化)就开始被使用的指针。
实际上上章笔记中delete关键字时就已经提到野指针的危害。因此进行delete以后应该从新new赋值或者设置为nullptr。
声明指针时,可在类型前、类型后或者两个地方都使用const。
const int *pOne;//指向常量的指针 int * const pTwo;//常量指针 const int * const pThree;//指向常量的常量指针三条语句意义各不相同,三个指针类型也各不相同。
pOne是指向整型常量的指针,也就是编译器默认它指向的是一个常量(虽然可能不是),因此不能经过这个指针来更改所指向的常量(编译器认为是常量但不必定是)的值,好比
*pOne = 5;
编译器就会报错。int one = 10; const int * pOne = &one; *pOne = 5;//报错,表达式必须是可修改的左值,但此时*pOne被认为不可修改pTwo是指向整型的常量指针,能够修改指向的整型变量,可是pTwo不能指向其余变量。
int two = 20; int * const pTwo = &two; *pTwo = 15; pTwo = &one;//报错,不能指向别的变量pThree是一个指向整型常量的常量指针,不能修改它指向的值,也不能让它指向其余变量。
int three = 30; const int * const pThree = &three; pThree = &one;//报错,不能指向别的变量 *pThree = 25;//报错,此时*pThree被认为不可修改
完整代码:(注释起来的是报错的)
#include <iostream> int main() { int one = 10; const int * pOne = &one; // *pOne = 5; int two = 20; int * const pTwo = &two; *pTwo = 15; // pTwo = &one; int three = 30; const int * const pThree = &three; // pThree = &one; // *pThree = 25; std::cout<<"one: "<<one<<" *pOne: "<<*pOne<<std::endl; std::cout<<"two: "<<two<<" *pTwo: "<<*pTwo<<std::endl; std::cout<<"three: "<<three<<" *pThree: "<<*pThree<<std::endl; return 0; }
程序清单11.5 ConstPointer.cpp
#include <iostream> class Rectangle { private: int itsLength; int itsWidth; public: Rectangle(); ~Rectangle(); void setLength(int length) { itsLength = length; } int getLength() const { return itsLength; } void setWidth(int width) { itsWidth = width; } int getWidth() const { return itsWidth; } }; Rectangle::Rectangle() : itsWidth(5), itsLength(10) //初始化列表 { } Rectangle::~Rectangle() {} int main() { Rectangle *pRect = new Rectangle; const Rectangle *pConstRect = new Rectangle; //pConstRect为指向Rectangle常量型对象的指针 Rectangle *const pConstPtr = new Rectangle; //pConstPtr为指向Rectangle型对象的常量指针 std::cout << "pRect width: " << pRect->getWidth() << " feet\n"; std::cout << "pConstRect width: " << pConstRect->getWidth() << " feet\n"; std::cout << "pConstPtr width: " << pConstPtr->getWidth() << " feet\n"; pRect->setWidth(10); //pConstRect->setWidth(10); pConstPtr->setWidth(10); std::cout << "pRect width: " << pRect->getWidth() << " feet\n"; std::cout << "pConstRect width: " << pConstRect->getWidth() << " feet\n"; std::cout << "pConstPtr width: " << pConstPtr->getWidth() << " feet\n"; return 0; }