当前时区为 UTC + 8 小时



发表新帖 回复这个主题  [ 5 篇帖子 ] 
作者 内容
1 楼 
 文章标题 : C++模板类继承中诡异的作用域问题
帖子发表于 : 2009-11-09 16:19 

注册: 2009-11-09 10:39
帖子: 4
送出感谢: 0 次
接收感谢: 0 次
C++模板类继承中诡异的作用域问题

帖子由 tiger » 2009-08-19 18:30
下面一段代码,大家可以试试,这样的问题经常被人忽略,出错还很难查:

代码: 全选
/*
* template_scope.cpp
*
* Created on: 2009-8-19 下午06:13:28
* Author: kwarph
* Web: http://www.xuanyuan-soft.cn
* Mail: kwarph@gmail.com
*/

#include <iostream>
using namespace std;

int x = 8;

void print() {
cout << "hello" << endl;
}

template<typename T>
class B {
public:
B() :
x(0) {
}

explicit B(const int& v) :
x(v) {
}

void print() const {
cout << "B::print()" << endl;
}

protected:
int x;
};

template<typename T>
class A: public B<T> {
public:
void test_scope() const {
cout << "x = " << x << endl; // 引用全局的x,输出 x = 8
// cout << "x = " << B<T>::x << endl; // 必须显式调用父类的x

print(); // 调用全局的print(),输出 hello
// B<T>::print(); // 必须显式调用父类的函数
}
};

class C {
public:
C() :
x(0) {
}

explicit C(const int& v) :
x(v) {
}

void print() const {
cout << "C::print()" << endl;
}

protected:
int x;
};

class D: public C {
public:
void test_scope() const {
cout << "x = " << x << endl; // 用父类的x,输出: x = 0
print(); // 调用父类的print(),输出: C::print()
}
};

int main() {
A<int> a;
a.test_scope();

D d;
d.test_scope();
}



但是非模板类继承就没有这些问题。


页首
 用户资料  
 
2 楼 
 文章标题 : Re: C++模板类继承中诡异的作用域问题
帖子发表于 : 2009-11-09 16:22 
头像

注册: 2007-08-05 17:40
帖子: 4968
送出感谢: 0 次
接收感谢: 4
请用code标签


_________________
free VPN
YouKuDownLoader
代码:
pip3 install ykdl

install YouKuDownLoader, have fun in downloading.
YouKuDownLoader所支持网站列表


页首
 用户资料  
 
3 楼 
 文章标题 : Re: C++模板类继承中诡异的作用域问题
帖子发表于 : 2009-11-18 17:26 
头像

注册: 2009-11-17 12:29
帖子: 883
送出感谢: 0 次
接收感谢: 0 次
有类型写清的东西就先用
找不到再考虑模板,这是编译器的一贯做法


页首
 用户资料  
 
4 楼 
 文章标题 : Re: C++模板类继承中诡异的作用域问题
帖子发表于 : 2009-11-19 17:26 
头像

注册: 2007-10-22 21:41
帖子: 63
送出感谢: 0 次
接收感谢: 0 次
嗯 C++ Template 中也提到过。
所以使用模板尽量用上 this->,不然会产生继承带来的问题。

想想也是,编译器现在对模板的东西是这样处理的:如果你不用(实例),就不对其进行编译(虽然只进行语法检查,但不进行语义检测),尤其是在成员模板函数上。
这个继承的问题,应该也是编译器偷懒的表现之一。
看看去了全局变量 print 之后的错误报告( g++ 4.3.3 ):

代码:
test.cpp: In member function ‘void A<T>::test_scope()’:
test.cpp:36: error: there are no arguments to ‘print’ that depend on a template parameter, so a declaration of ‘print’ must be available
test.cpp:36: error: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)


看,print 需要参数来制定。所以说 模板成员函数必须要显示指定参数( 类指针) : this->print().

没看过 C++ 的编译器源码,猜测可能是这样子:
编译到 A<int> 会实例化 A<int>, 继而是 B<int>, 形成一些类签名。这里只是实例化了类内的成员变量。成员函数又不影响类的结构变化,所以一般会将 成员函数游离在类基本结构之外,可以看看 C++ 对象结构的书,大部分编译器都是这样分开处理的。
然后编译 a.test_scope(), 编译到 print() 时,开始在当前符号表和outer 符号表中搜寻,因为模板类的成员函数是用到的时候才编译,才能加入到符号表中,所以这个时候就只找到 全局的print() 符号了。但是有了 this 就不同了,会从当前类域向基类域查找,如果是模板函数会实例化,并加入到符号表中。

猜测是这个样子,看样子得研究下 C++ 的编译器才行。

这个特性应该算是标准吧,现在。可以利用这个特性来进行一些模板元编程。


页首
 用户资料  
 
5 楼 
 文章标题 : Re: C++模板类继承中诡异的作用域问题
帖子发表于 : 2009-11-19 20:31 
头像

注册: 2009-11-17 12:29
帖子: 883
送出感谢: 0 次
接收感谢: 0 次
其实写代码的时候 写明this 指针是个好习惯,不能总是想着依赖符号可见范围。。

很容易出问题

另外就是LS的ERROR中提到了 -fpermissive,这个选项在编译Win32程序时常常要用到。。


页首
 用户资料  
 
显示帖子 :  排序  
发表新帖 回复这个主题  [ 5 篇帖子 ] 

当前时区为 UTC + 8 小时


在线用户

正在浏览此版面的用户:没有注册用户 和 2 位游客


不能 在这个版面发表主题
不能 在这个版面回复主题
不能 在这个版面编辑帖子
不能 在这个版面删除帖子
不能 在这个版面提交附件

前往 :  
本站点为公益性站点,用于推广开源自由软件,由 DiaHosting VPSBudgetVM VPS 提供服务。
我们认为:软件应可免费取得,软件工具在各种语言环境下皆可使用,且不会有任何功能上的差异;
人们应有定制和修改软件的自由,且方式不受限制,只要他们自认为合适。

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
简体中文语系由 王笑宇 翻译