C++中如何将一个类的this传递到类外面使用,用静态成员变量初始化保存为什么会出错,求高手赐教?

来 自:北京
等 级:贵宾
威 望:94
帖 子:6779
专家分:16751
&&得分:10&
第一个我觉得第一种好,要不然 p1, p2 谁来初始化?
第二个,如果你想写模版的还应该写成:
template &class T&
int Point&T&::Num = 0;
int Point&int&::Num = 0;
不是用来初始使模版的,这是特化,就是说当 T 是 int 的时候是这样。其它的不管。
即使有两个都写也没是,当 T 是 int 的时候用的是下面的。其它是时候用上面的。
等 级:论坛游民
专家分:14
&&得分:10&
第一个问题:声明类时是不分配内存的,因此要通过要通过构造函数初始化子对象。
第二个问题:在初始化静态数据成员之前加上
template &class T&
float Point&T&::Num=0;//静态数据成员只能在类外初始化
等 级:新手上路
谢谢两位~~
第二个问题弄清楚了
但第一个问题还有点不懂:p1,p2是里面的成员,一定要初始化么
来 自:北京
等 级:贵宾
威 望:94
帖 子:6779
专家分:16751
看你这个类是怎么设计的了。其实如果只要记一个距离的话,去掉那两个成员也可以。
等 级:新手上路
恩,懂了,太感谢了
版权所有,并保留所有权利。
Powered by , Processed in 0.026789 second(s), 8 queries.
Copyright&, BCCN.NET, All Rights Reserved&&问题点数:0&&回复次数:13&&&
谁知道在c++中怎么在模板中使用静态变量啊?
在学到c++模板时,忽然想到静态变量,于是试一下,但是出不了结果,不知道使用时有什么规则?请哪位高手指教一下!!
搜索更多相关主题的帖子:
等 级:新手上路
帖 子:41
具体点吧!大家看看这是怎么错的?
#include&iostream.h&
template &class T&
Fun(int i=1)
p=new T[i];
void input();
void output();
void sort();
void look(T);
void add()
&&&&for(int i=0;i&l;i++)
&&&&&& sum+=p[i];
~Fun(){delete []}
T static::sum=0;
4template &class T&
void Fun&T&::input()
{ for(int i=0;i&l;i++)
{ cout&&&请输入第&&&i+1&&&个数据:&;
&&& cin&&p[i];
template &class T&
void Fun&T&::output()
{for(int i=0;i&l;i++)
&&cout&&p[i]&&' ';
template &class T&
void Fun&T&::sort()
for(int i=0;i&l-1;i++)
&&for(int j=i+1;j&l;j++)
&&&&&&if(p[i]&p[j])
&&&&&&{tem=p[i];
&&&&&&&p[i]=p[j];
&&&&&&&p[j]=
template &class T&
void Fun&T&::look(T key)
{for(int i=0;i&l;i++)
&&if(p[i]!=key)
&&else cout&&&您要的数据在第&&&i+1&&&个&;
cout&&&抱歉~您要的数据没有查询到!请从新输入:&;
void main()
{Fun&int& s(4);
cout&&&请输入数据:&;
s.input();cout&&
cout&&&确认您的数据为:&;
s.output();cout&&
cout&&&对您的数据排序后结果:&;
s.output();cout&&
cout&&&请输入您要查询的数据:&;
s.look(key);
谢谢啊很多 麻烦大家啦
等 级:新手上路
帖 子:114
我也不大清楚,但是把T static::sum=0;这句变成int sum=0;编译的时候就没有提示错误了。~~~
等 级:新手上路
帖 子:41
谢谢楼上的朋友啊!我上面的程序写的有点问题~~~不好意思
#include&iostream.h&
template &class T&
Fun(int i=1)
p=new T[i];
void input();
void output();
void sort();
void look(T);
void add()
&&&&for(int i=0;i&l;i++)
&&&&&& sum+=p[i];
~Fun(){delete []}
T&&Fun::sum=0;
template &class T&
void Fun&T&::input()
{ for(int i=0;i&l;i++)
{ cout&&&请输入第&&&i+1&&&个数据:&;
&&& cin&&p[i];
template &class T&
void Fun&T&::output()
{for(int i=0;i&l;i++)
&&cout&&p[i]&&' ';
template &class T&
void Fun&T&::sort()
for(int i=0;i&l-1;i++)
&&for(int j=i+1;j&l;j++)
&&&&&&if(p[i]&p[j])
&&&&&&{tem=p[i];
&&&&&&&p[i]=p[j];
&&&&&&&p[j]=
template &class T&
void Fun&T&::look(T key)
{int k=-1;
&&&&for(int i=0;i&l;i++)
&&&&if(p[i]==key) k=i;
&&&&if(k!=-1) cout&&&您要的数据在第&&&k+1&&&个&;
&&& else cout&&&抱歉~您要的数据没有查询到!请从新输入:&;
void main()
{Fun&int& s(4);
cout&&&请输入数据:&;
s.input();cout&&
cout&&&确认您的数据为:&;
s.output();cout&&
cout&&&对您的数据排序后结果:&;
s.output();cout&&
cout&&&请输入您要查询的数据:&;
s.look(key);
请高手们在看看啊!~~~多谢啊
来 自:湖北工业大学
等 级:贵宾
威 望:19
帖 子:3946
专家分:748
程序代码:#include &iostream&
&&&&A(int n):v2(n){}
&&&&static int v1;
&&&&const int v2;
&&&&static const int v3=3;
int A::v1=1;
int main(){
&&&&printf(&%d&,sizeof(A));
&&&&getchar();
}请看这个例子。运行结果是4,也就是说,只有一个成员是属于对象的,是哪一个呢?是v2!其实编译时,所有的静态变量都是在静态变量区定义的。虽然v2是常量,但是也是要占内存空间的,这其实就是C++里面常量和C里面的预处理符号常量的最大区别:C的符号常量是不占内存空间的……
那么如果使用模板怎么办呢?程序代码:#include &iostream&
template&class T&
&&&&A(T n):v2(n){}
&&&&static T v1;
&&&&const T v2;
&&&&static const T v3=3;
template&class T&
T A&T&::v1=1;
int main(){
&&&&printf(&%d&,sizeof(A&int&));
&&&&getchar();
}请注意代码的变化。模板类是在每一次实例化的时候编译的,换句话说,如果代码里面没有用到模板类,那么类里面的语法错误就永远不会被发现。
还有,大家可以吧A&int&换成A&float&看看是什么结果。嘿嘿~~~
静态/常量变量和模板都是比较难理解的概念。静态/常量变量掌握变量的内存布局就不会出错了,而模板则需要仔细分析程序的语法结构才能正确使用。
专心编程………
飞燕算法初级群:3996098
等 级:新手上路
帖 子:41
谢谢这位仁兄啊 ~~~~·终于解决了!
还是现代人思维活跃啊 ~~~~我问老师,他们都说没见过!
哈哈呵…………
等 级:新手上路
帖 子:41
请再指教一下啊~~~~~
那你怎么在你上面写的程序中,怎么在主函数中用那个静态变量呢?
#include &iostream&
template&class T&
&&& A(T n):v2(n){}
&&& static T v1;
&&& const T v2;
&&& static const T v3;
template&class T&
T A&T&::v1=1;
template&class T&
T A&T&::v3=1;
int main(){
&&&&A&int& a(10);
&&&&cout&&&v2=&&&a.v2&&
&&&&cout&&&v3=&&&A::v3;//这个v3怎么用啊?
&&printf(&%d&,sizeof(A&int&));
&&& getchar();
来 自:湖北工业大学
等 级:贵宾
威 望:19
帖 子:3946
专家分:748
首先要明白一个观点,也就是变量的所有权的问题。一个类的成员变量总是属于该类的对象的。但并不是所有的成员变量都是属于这个类的,事实上只有一种成员变量(或函数)是属于类的,也就是静态成员变量(函数)。
在这个问题上,我表示抱歉,我在上面说:“也就是说,只有一个成员是属于对象的”。其实这种说法是不科学的,因为那三个变量都是属于对象的。应该说“只有一个成员是对象的一部分”。属于和由什么组成是两个概念。这支钢笔是属于我的,但是钢笔显然不是长在我的身上的!
所以一方面v3可以这么用:
但是,static声明的变量不止是属于对象的,还是属于这个类的,所以V3和V1还可以这么用
A::V3//v1是一样的
慢着!编译出错了!
原来,A是模板类,永远记住,模板类是需要模板参数的,于是改成如下的语法:
A&int&::V3
这里要注意,因为V3是在类里面直接赋值的,所以这里类型声明只能是整型(char,short,int,long)否则会出编译错误,其实正因为V3是在类里面直接赋值的,而且又是只读的,所以模板参数也是无所谓的。
还有要说的是,你写的代码中V3的初始化的方法是错误的。记住,static必须在类外初始化,const必须在构造函数初始化表初始化,static const可以在类的外面也可以在里面初始化,但是要带上const修饰符。把这三种情况当作公式背下来就不会再出错了。
[[italic] 本帖最后由 StarWing83 于
13:33 编辑 [/italic]]
专心编程………
飞燕算法初级群:3996098
等 级:新手上路
帖 子:41
先谢谢这位仁兄啊!
首先,七楼的那个程序是复制你的,我只是简单的改动一下,在机子上运行是没有错误的。
另外,“static const必须在声明的时候就初始化”我不知对不对,但是,我在c++6.0
运行时老是编译错误~~但是,改成“template&class T&
T A&T&::v3=1;
”之后就能通过编译!并且结果正确。
最后十分感谢您啊~~~就剩一个问题了,就是上面的那一个&static const&问题。
来 自:湖北工业大学
等 级:贵宾
威 望:19
帖 子:3946
专家分:748
这个可能是编译器的问题吧。我用的VC++2005……VC6对C++的标准实现不好……还有,就是static const是可以在里面也可以在外面声明的,但是如果在外面,就必须这么写:
template&class T&
const T A&T&::v3=1;
因为V3是个常量变量……我昨天编译失败就是这个原因,这样就不会出问题了。记住,VC6对C++的实现是不完整的。这里再引用《C++ Primer》里面的一段话:
Ordinarily, class static members, like ordinary data members, cannot be initialized in the class body. Instead, static data members are normally initialized when they are defined.
One exception to this rule is that a const static data member of integral type can be initialized within the class body as long as the initializer is a constant expression:
&&&&&&class Account {
&&&&&&public:
&&&&&&&&& static double rate() { return interestR }
&&&&&&&&& static void rate(double);&&&// sets a new rate
&&&&&&private:
&&&&&&&&& static const int period = 30; // interest posted every 30 days&&&这里,static const可以直接在类内部定义,其余情况都必须在外部实现,另外,static成员的定义必须放在CPP文件中,防止重复声明
&&&&&&&&& double daily_tbl[period]; // ok: period is constant expression
A const static data member of integral type initialized with a constant value is a constant expression. As such, it can be used where a constant expression is
required, such as to specify the dimension for the array member daily_tbl.
When a const static data member is initialized in the class body, the data member must still be defined outside the class definition.
When an initializer is provided inside the class, the definition of the member must not specify an initial value:
&&&&&&// definition of static member
&&&&&&// the initial value is specified inside the class definition
&&&&&&const int Account::
专心编程………
飞燕算法初级群:3996098
版权所有,并保留所有权利。
Powered by , Processed in 0.032745 second(s), 8 queries.
Copyright&, BCCN.NET, All Rights ReservedC++中的静态成员变量和静态成员函数
  (1)类静态数据成员在编译时创建并初始化:在该类的任何对象建立之前就存在,不属于任何对象,而非静态类成员变量则是属于对象所有的。类静态数据成员只有一个拷贝,为所有此类的对象所共享。特别需要注意的一点是:静态数据成员不能在类中初始化(对于常量静态类变量有待考证,好像可以在类外或main()函数之前定义,初始化可以放在类中),一般在类外和main()函数之前初始化,缺省时初始化为0。静态数据成员用来定义类的各个对象所公有的数据,比全局变量更安全。
  (2)类静态成员函数属于整个类,不属于某个对象,由该类所有对象共享。静态成员可定义为inline函数。一般情况下静态成员函数用于访问同一类中的静态数据成员或全局变量,而不访问非静态成员,如需访问非静态成员,需要将对象作为参数,通过对象名访问该对象的非静态成员。静态成员函数也可以在类外定义,此时不可以用static修饰。静态成员函数存在的原因是什么呢?主要是在建立任何对象之前可用它来访问静态数据成员,普通函数不能实现此功能。
  C++静态成员和静态成员函数的使用:静态成员的调用格式:类名::静态数据成员名、对象名.静态数据成员名、对象指针-&静态数据成员、对象引用.静态数据成员(但类中很少会出现公有数据成员,这段仅仅讨论语法,未考虑实际运用中的数据封装问题)。静态成员函数的调用格式:类名::静态成员函数名、对象名.静态成员函数名、对象指针-&静态成员函数名、对象引用.静态数据成员。静态成员函数没有this指针,因它不与特定对象相联系,调用时推荐使用“类名::静态成员函数名”格式。总结来说,在有对象的情况下,可以用调用普通类成员函数、普通成员变量的方式调用静态成员函数和静态成员变量。从这里可以看出静态成员变量和静态成员函数的使用应该是在不建立任何对象的情况下调用它们。其应用可以参见设计模式中Singleton
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:347827次
积分:6177
积分:6177
排名:第1285名
原创:175篇
转载:700篇
评论:61条
(6)(8)(20)(11)(5)(5)(8)(2)(10)(24)(32)(40)(15)(31)(19)(20)(8)(3)(25)(39)(28)(19)(5)(3)(3)(1)(4)(2)(9)(13)(17)(18)(18)(41)(32)(17)(45)(60)(51)(49)(55)(56)有下面的一个简单的类:
class&CNullPointCall
&&&&static&void&Test1();
&&&&void&Test2();
&&&&void&Test3(int&iTest);
&&&&void&Test4();
&&&&static&int&m_iS
&&&&int&m_iT
int&CNullPointCall::m_iStatic&=&0;
void&CNullPointCall::Test1()
&&&&cout&&&&m_iStatic&&&&
void&CNullPointCall::Test2()
&&&&cout&&&&&Very&Cool!&&&&&&
void&CNullPointCall::Test3(int&iTest)
&&&&cout&&&&iTest&&&&&
void&CNullPointCall::Test4()
&&&&cout&&&&m_iTest&&&&&
&&& 那么下面的代码都正确吗?都会输出什么?
CNullPointCall&*pNull&=&NULL;&//&没错,就是给指针赋值为空
pNull-&Test1();&//&call&1
pNull-&Test2();&//&call&2
pNull-&Test3(13);&//&call&3
pNull-&Test4();&//&call&4
&&& 你肯定会很奇怪我为什么这么问。一个值为NULL的指针怎么可以用来调用类的成员函数呢?!可是实事却很让人吃惊:除了call 4那行代码以外,其余3个类成员函数的调用都是成功的,都能正确的输出结果,而且包含这3行代码的程序能非常好的运行。
&&& 经过细心的比较就可以发现,call 4那行代码跟其他3行代码的本质区别:类CNullPointCall的成员函数中用到了this指针。
&&& 对于类成员函数而言,并不是一个对象对应一个单独的成员函数体,而是此类的所有对象共用这个成员函数体。 当程序被编译之后,此成员函数地址即已确定。而成员函数之所以能把属于此类的各个对象的数据区别开, 就是靠这个this指针。函数体内所有对类数据成员的访问, 都会被转化为this-&数据成员的方式。
&&& 而一个对象的this指针并不是对象本身的一部分,不会影响sizeof(“对象”)的结果。this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。也就是说,即使你没有写上this指针,编译器在编译的时候也是加上this的,它作为非静态成员函数的隐含形参,对各成员的访问均通过this进行。
&&& 对于上面的例子来说,this的值也就是pNull的值。也就是说this的值为NULL。而Test1()是静态函数,编译器不会给它传递this指针,所以call 1那行代码可以正确调用(这里相当于CNullPointCall::Test1());对于Test2()和Test3()两个成员函数,虽然编译器会给这两个函数传递this指针,但是它们并没有通过this指针来访问类的成员变量,因此call 2和call 3两行代码可以正确调用;而对于成员函数Test4()要访问类的成员变量,因此要使用this指针,这个时候发现this指针的值为NULL,就会造成程序的崩溃。&&&&
&&& 其实,我们可以想象编译器把Test4()转换成如下的形式:
void&CNullPointCall::Test4(CNullPointCall&*this)
&&&&cout&&&&this-&m_iTest&&&&&
&&& 而把call 4那行代码转换成了下面的形式:
CNullPointCall::Test4(pNull);
&&& 所以会在通过this指针访问m_iTest的时候造成程序的崩溃。
&&& 下面通过查看上面代码用VC 2005编译后的汇编代码来详细解释一下神奇的this指针。
&&& 上面的C++代码编译生成的汇编代码是下面的形式:
&&&&CNullPointCall&*pNull&=&NULL;
0041171E&&mov&&&&&&&&&dword&ptr&[pNull],0&
&&&&pNull-&Test1();
&&call&&&&&&&&CNullPointCall::Test1&(411069h)&
&&&&pNull-&Test2();
0041172A&&mov&&&&&&&&&ecx,dword&ptr&[pNull]&
0041172D&&call&&&&&&&&CNullPointCall::Test2&(4111E0h)&
&&&&pNull-&Test3(13);
&&push&&&&&&&&0Dh&&
&&mov&&&&&&&&&ecx,dword&ptr&[pNull]&
&&call&&&&&&&&CNullPointCall::Test3&(41105Ah)&
&&&&pNull-&Test4();
0041173C&&mov&&&&&&&&&ecx,dword&ptr&[pNull]&
0041173F&&call&&&&&&&&CNullPointCall::Test4&(411032h)&
&&& 通过比较静态函数Test1()和其他3个非静态函数调用所生成的的汇编代码可以看出:非静态函数调用之前都会把指向对象的指针pNull(也就是this指针)放到ecx寄存器中(mov ecx,dword ptr [pNull])。这就是this指针的特殊之处。看call 3那行C++代码的汇编代码就可以看到this指针跟一般的函数参数的区别:一般的函数参数是直接压入栈中(push 0Dh),而this指针却被放到了ecx寄存器中。在类的非成员函数中如果要用到类的成员变量,就可以通过访问ecx寄存器来得到指向对象的this指针,然后再通过this指针加上成员变量的偏移量来找到相应的成员变量。
&&& 下面再通过另外一个例子来说明this指针是怎样被传递到成员函数中和如何使用this来访问成员变量的。
&&& 依然是一个很简单的类:
class&CTest
&&&&void&SetValue();
&&&&int&m_iValue1;
&&&&int&m_iValue2;
void&CTest::SetValue()
&&&&m_iValue1&=&13;
&&&&m_iValue2&=&13;
&&& 用如下的代码调用成员函数:
test.SetValue();
&&& 上面的C++代码的汇编代码为:
&&&&CTest&
&&&&test.SetValue();
004117DC&&lea&&&&&&&&&ecx,[test]&
004117DF&&call&&&&&&&&CTest::SetValue&(4111CCh)&
&&& 同样的,首先把指向对象的指针放到ecx寄存器中;然后调用类CTest的成员函数SetValue()。地址4111CCh那里存放的其实就是一个转跳指令,转跳到成员函数SetValue()内部。
004111CC&&jmp&&&&&&&&&CTest::SetValue&(411750h)
&&& 而411750h才是类CTest的成员函数SetValue()的地址。
void&CTest::SetValue()
&&push&&&&&&&&ebp&&
&&mov&&&&&&&&&ebp,esp&
&&sub&&&&&&&&&esp,0CCh&
&&push&&&&&&&&ebx&&
0041175A&&push&&&&&&&&esi&&
0041175B&&push&&&&&&&&edi&&
0041175C&&push&&&&&&&&ecx&//&1&&&
0041175D&&lea&&&&&&&&&edi,[ebp-0CCh]&
&&mov&&&&&&&&&ecx,33h&
&&mov&&&&&&&&&eax,0CCCCCCCCh&
0041176D&&rep&stos&&&&dword&ptr&es:[edi]&
0041176F&&pop&&&&&&&&&ecx&//&2&
&&mov&&&&&&&&&dword&ptr&[ebp-8],ecx&//&3
&&&&m_iValue1&=&13;
&&mov&&&&&&&&&eax,dword&ptr&[this]&//&4
&&mov&&&&&&&&&dword&ptr&[eax],0Dh&//&5
&&&&m_iValue2&=&13;
0041177C&&mov&&&&&&&&&eax,dword&ptr&[this]&//&6
0041177F&&mov&&&&&&&&&dword&ptr&[eax+4],0Dh&//&7
&&pop&&&&&&&&&edi&&
&&pop&&&&&&&&&esi&&
&&pop&&&&&&&&&ebx&&
&&mov&&&&&&&&&esp,ebp&
0041178B&&pop&&&&&&&&&ebp&&
0041178C&&ret&
&&& 下面对上面的汇编代码中的重点行进行分析:
&&& 1、将ecx寄存器中的值压栈,也就是把this指针压栈。
&&& 2、ecx寄存器出栈,也就是this指针出栈。
&&& 3、将ecx的值放到指定的地方,也就是this指针放到[ebp-8]内。
&&& 4、取this指针的值放入eax寄存器内。此时,this指针指向test对象,test对象只有两个int型的成员变量,在test对象内存中连续存放,也就是说this指针目前指向m_iValue1。
&&& 5、给寄存器eax指向的地址赋值0Dh(十六进制的13)。其实就是给成员变量m_iValue1赋值13。
&&& 6、同4。
&&& 7、给寄存器eax指向的地址加4的地址赋值。在4中已经说明,eax寄存器内存放的是this指针,而this指针指向连续存放的int型的成员变量m_iValue1。this指针加4(sizeof(int))也就是成员变量m_iValue2的地址。因此这一行就是给成员变量m_iValue2赋值。
&&& 通过上面的分析,我们可以从底层了解了C++中this指针的实现方法。虽然不同的编译器会使用不同的处理方法,但是C++编译器必须遵守C++标准,因此对于this指针的实现应该都是差不多的
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:303216次
积分:4234
积分:4234
排名:第2526名
原创:111篇
转载:102篇
评论:175条
创业进行中。。。。《马上赚钱》国内第一高收益赚钱应用,百万用户鼎立推荐,利用碎片时间,每天几分钟,动动手指也能轻松赚钱、赚话费、Q币,更能提现到支付宝下载地址:http://a./o/simple.jsp?pkgname=com.apptreehot.horse。下载地址:见二维码头像
(2)(3)(1)(4)(1)(7)(5)(1)(4)(3)(4)(5)(7)(6)(29)(26)(24)(24)(22)(13)(3)(8)(3)(4)(4)}

我要回帖

更多关于 静态成员变量初始化 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信