class Window {
public:
virtual void onResize(){...}
...
};
class SpecialWindow :public Window {
public:
virtual void onResize() {
static_cast<Window>(*this).onResize();//derived onResize实现代码
//将*this转型为Window,然后调用其onResize,行不通,见分析
}
};
*this 对象转型成 base 类,相当于创建了一个临时对象;如果这段代码的原意是想要调用 onResize 修改 base 部分的变量,这里就变了味,因为这只能修改临时变量中的 base 部分,正确的方法应该是将转型放入函数中:class SpecialWindow :public Window {
public:
virtual void onResize() {
Window::onResize();//调用Window::onResize作用于*this身上,此处使用了作用域操作符
}
};
class Point {
public:
Point(int x, int y);
void setX(int newVal);
void setY(int newVal);
}
struct RectData {
Point ulhc;//ulhc="upper left-hand corner"(左上角)
Point lrhs;//lrhc="lower right-hand corner"(右下角)
};
class Rectangle {
private:
shared_ptr<RectData> pData;// 要注意这里是private的,本意就是不想被修改
public:
Point& upperLeft()const { return pData -> ulhc; }//这里可不是条款21说的返回对象的引用
Point& lowerRight()const { return pData->lrhc; }
};
Point coord1(0, 0);
Point coord2(100, 100);
const Rectangle rec(coord1, coord2);
rec.upperLeft().setX(50);//此处ulhc与lrhc都被声明为private,但实际上却是public,
//因为仍然是在直接修改私有成员。
// 这里能被修改的原因就是函数返回的是 `Point&`,与本条款的内容相违背
// 对此进行改进如下:【还要注意尽量防止 handle 管理一个空对象】
class Rectangle {
private:
shared_ptr<RectData> pData;
public:
const Point& upperLeft()const { return pData->ulhc; }
const Point& lowerRight()const { return pData->lrhc; }
};
// 但这里仍然是返回了handles,可能会造成dangling(空悬的) handles,空悬的意思是handles所真正指的东西不复存在
// 错误的代码使用如下:
class GUIObject{};
const Rectangle boundingBox(const GUIObject& obj);
//客户使用这个函数:
GUIObject* pgo;
const Point& pUpperLeft = &(boundingBox(*pgo).upperLeft());
// 上面这个式子的问题在于:boundingBox是值传递,返回了一个无名的临时值
// 这个临时值调用upperLeft产生的引用也是临时对象内部的,所以后面会dangling
a、b 和 ab,头文件将类的声明和类的实现分开,这样就有 6 个文件(3 个 h 文件和 3 个 cpp 文件);且假设 ab 是由 a 和 b 复合而来,a 和 b 也相互独立。【意思就是 ab 的 h 头文件必须包含 a 和 b 的 h 头文件】a 类(即告知编译器 a 的存在),这样仍然是不能通过编译的。【因为编译器需要确切知道 ab 类中 a 成员变量的大小】【如果 a 只是作为形参或返回值,声明一下又是可以的】a 的实现,变成是成员变量指针 a。【指针大小是确定的】
a 即可;因为 ab.h 也不包括实现,所以这里不会用到 a 中的方法;ab.cpp 进行真正的实现,再包含文件即可。a 的 class),ab.cpp 包含了 a.h,那实现里还是包括了 a.h,好处究竟在哪里?
a 的改变影响不了所有包含 ab.h 的地方。Person(包含指针的那个类),而不必关心 PersonImp(真正实现),用于幕后实现的 PersonImp 只面向于软件开发者而不是使用者。【以后 Person 添加成员变量,可以直接在 PersonImp 中进行添加了,从而起到了隔离和隐藏的作用】Person 成为一种特殊的 abstract base class(抽象基类),称为 Interface class。
Create 函数声明,子类将虚方法实现,并实现 Create 接口。Person 的引用或者指针,就可以访问到子类的方法。