您的位置:首页 > 编程语言 > C语言/C++

策略模式(2)——c++接口类的实现

2011-08-26 02:47 162 查看
c++不像java一样有纯接口类的的语法,但我们可以通过一些手段实现相同的功能。

一:

考虑这样的代码:

class A

{

protected:

virtual ~A()

{

cout << __FUNCTION__ << endl;

}

};

class B : public A

{

public:

virtual ~B()

{

cout << __FUNCTION__ << endl;

}

};

int _tmain(int argc, _TCHAR* argv[])

{

A* p1 = new A; //[1]有问题

delete p1;

B* p2 = new B;

delete p2; //[2]没问题的

A* p3 = new B;

delete p3; //[3] 有问题

return 0;

}

通过在类中,将类的构造函数或者析构函数申明成protected ,可以有效防止类被实例话,要说实用的话,构造函数是protected更有用,肯定能保证类不会被实例化,而如果析构函数是protected的话,构造函数不是protected的话,还可能存在编译通过的漏洞,如下:

A:

class A

{

protected:

A()

{

cout << __FUNCTION__ << endl;

}

};

int _tmain(int argc, _TCHAR* argv[])

{

A* p1 = new A; //编译不通过,无法访问protected构造函数

delete p1;

return 0;

}

B:

class A

{

protected:

~A()

{

cout << __FUNCTION__ << endl;

}

};

int _tmain(int argc, _TCHAR* argv[])

{

A* p1 = new A; //编译通过,此时因为仅仅是用到了A的构造函数,还不需要它的析构函数

return 0;

}

C:

class A

{

protected:

~A()

{

cout << __FUNCTION__ << endl;

}

};

int _tmain(int argc, _TCHAR* argv[])

{

A* p1 = new A;

delete p1; //编译失败,因为编译器发现A的析构函数是protected

return 0;

}

所以,一种可行的办法貌似是这样的:

class A

{

protected:

virtual ~A()

{

cout << __FUNCTION__ << endl;

}

};

class B : public A

{

};

int _tmain(int argc, _TCHAR* argv[])

{

B* p =new B; //这种情况下确实是可行的

delete p;

return 0;

}

由于B public继承自A,所以其可以完全访问A的构造或析构函数,但是:

int _tmain(int argc, _TCHAR* argv[])

{

A* p =new B;

delete p; //由于p变成指向A的指针,字面上编译器需要知道A的析构函数,然后A的析构函数又是protected

return 0;

}

即便像这样B显示重载了A的析构函数:

class A

{

protected:

virtual ~A()

{

cout << __FUNCTION__ << endl;

}

};

class B : public A

{

public:

virtual ~B()

{

cout << __FUNCTION__ << endl;

}

};

int _tmain(int argc, _TCHAR* argv[])

{

A* p =new B;

delete p; //也还是不行,因为重载是运行时的事情,在编译时编译器就认定了A的析构函数,结果无法获取

return 0

}

小结:

貌似用protected这样的方法并不是很恰当,虽然在遵守一定规则的情况下确实有他的实用价值,但并不是很通用。

二:

其实上面protected的思路是对的,无非是让父类无法实例化,那么为了让父类无法实例化,其实还有一个方法,使用纯虚函数。

class A

{

public: //这里就不用protected了

virtual ~A() = 0;

};

class B : public A

{

};

int _tmain(int argc, _TCHAR* argv[])

{

B* p =new B;

delete p;

return 0;

}

这样写貌似不错,以往大家都把类中的一般成员函数写成纯虚的,这次将析构函数写成纯虚的,更加增加通用性,编译也通过了,但就是在链接的时候出问题,报错说找不到A的析构函数的实现,很显然吗,因为A的析构是纯虚的吗。

class A

{

public: //这里就不用protected了

virtual ~A() = 0 //它虽然是个纯虚函数,但是默认实现,可以有

{ //这个语法很好很强大,经过小强的指点终于高清了他的用法(完全是为了实现其接口类而弄的语法吧)

cout << __FUNCTION__ << endl;

}

};

class B : public A

{

};

int _tmain(int argc, _TCHAR* argv[])

{

B* p =new B;

delete p;

A* p2 =new B;

delete p2; //不用担心编译器报错了,因为此时A的析构函数是public

return 0;

}

如此终于大功告成了,注意,不能将构造函数替代上面的析构函数的用法,因为构造函数是不允许作为虚函数的。

补充:以上那个语法就真的只是为了这种情况而存在的,因为一般我们在虚类中申明的接口:

virtual foo() = 0;

virtual foo() = 0 {}

这两种写法是完全没有区别的,纯虚函数的默认实现,仅仅在它是析构函数中才有意义!!!

所以可以说,老外是完全为了这一个目的而发明了这种语法...

最终的接口类

class Interface

{

public:

virtual ~Interface() = 0 {}

};

应该挺完美的了吧,hiahia
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: