c++编程思想中的重载操作符一节中关于灵巧指针(->)有些不理解
class obj{
...
public:
void f(){...};
viod g(){...};
};
class sp{
...
obj* objector->(){ //重载->操作符
...}
};
main()
{
sp SP;
SP->f();
}
上面主程序中SP->调用重载操作符后,返回的应该是个指针(指向obj对象),这个指针要调用f()成员是否应该再来一个“->”?即:SP->->f().
问题点数:120、回复次数:22Top
1 楼coolxiao(coolxiao)回复于 2001-05-23 09:48:00 得分 0
我估计这时候c++会先匹配了系统运算符 Point->Member,因为你重载后的->只是单目运算,我想不会先匹配的。具体情况我也没有试 过,最后自己动手做一做Top
2 楼coolxiao(coolxiao)回复于 2001-05-23 09:49:00 得分 20
sorry,看错了,SP不是指针,那我说错了=)Top
3 楼wagnerwash()回复于 2001-05-23 10:27:00 得分 0
->是2元操作符,你重载的语法不对!Top
4 楼sequoia_96(牛琴乱弹)回复于 2001-05-23 10:30:00 得分 0
我想因该不能编译通过吧,像楼上说的。具体我也没试过,最好自己编译以下Top
5 楼eggplant(拉拉)回复于 2001-05-23 11:27:00 得分 20
class CA
{
public:
virtual void func1{}();
}
class CB
{
public:
CB(CA* p){m_p=p;}
CA* operator ->(){return m_p;}
private:
CA* m_p;
}
一个使用例子:
CA* pa= new CA;
CB* pb= new CB(pa);
CA* pa2= pb->operator ->();
下面是MSDN的说明:
Class-Member Access
Class-member access can be controlled by overloading the member-selection operator (–>). This operator is considered a unary operator in this usage, and the overloaded operator function must be a class member function. Therefore, the declaration for such a function is:
class-type *operator–>()
where class-type is the name of the class to which this operator belongs. The member-selection operator function must be a nonstatic member function.
This operator is used (often in conjunction with the pointer-dereference operator) to implement “smart pointers” that validate pointers prior to dereference or count usage.
The . member-selector operator cannot be overloaded.
Top
6 楼liu_feng_fly(笑看风云 搏击苍穹 衔日月)回复于 2001-05-23 11:56:00 得分 0
??Top
7 楼jy(树,路)回复于 2001-05-23 12:25:00 得分 0
典型的实现是COM的智能接口指针(Smart Interface Pointers)。
关于这个,可以参阅MSDN中标题为“Calling COM Objects with Smart Interface Pointers”的文章,我相信看完就会明白了。
另外,千真万确:->是一个一元操作符。前面eggplant的语法是正确的。Top
8 楼fresh_(fresh_)回复于 2001-05-23 16:37:00 得分 0
to eggplant:
期待你将例子做下去。
你的使用例子:
CA* pa= new CA;
CB* pb= new CB(pa);
CA* pa2= pb->operator ->();
如果接下去要使用pa2的func1,该怎么写?是这样吗?
CA* pa= new CA;
CB* pb= new CB(pa);
CA* pa2= pb->operator ->();
pa2->func1();
回到我的问题上,如果不定义pa2,而直接使用pb->operator ->()返回的临时指针直接调用func1,即:将第3、4行合并,该变成什么样?
1)pb->operator->()->func1(); 还是 2)pb->operator->func1();
我觉得因该是1)
可书上是2)(c++编程思想p214,line 3或4)
所以来此向大家请教。
Top
9 楼jy(树,路)回复于 2001-05-24 03:38:00 得分 60
应该是pb->operator->()->func1();
你是对的。
2)是肯定错的。不可能产生出那样的语序。
你如果真的想使用smart机制,应该这样:
CB b(pa);
b->func1();
///////////////////////////////////////////////////////////
是的,b是一个对象,而不是真正的指针;
把b当作一个指针来使用,正是重载->的目的。
这样,才体现出C++之强大:紧凑,直观(在理解的基础上,这是直观的)。试想焉能不为之着魔?
COM对象保留一个引用计数,所以使用灵巧指针机制对计数进行维护。
(c++编程思想p214,line 3或4)
抱歉我还没看这书,但是,你确信?我不大信它这样子犯错。
Top
10 楼jy(树,路)回复于 2001-05-24 03:49:00 得分 0
想想自己说得太满,呵呵,赶紧验证了一下,现在郑重宣布,我的说法是正确的,你的那个TICA书是错的。Top
11 楼fresh_(fresh_)回复于 2001-05-24 09:50:00 得分 0
这本书上几乎全是这样使用,(如p309,倒数第5行等),难道全错了?我觉得不太可能,在程序中将两种写法都用了一下,效果居然一样。真是奇怪,难道1)、2)两种写法等价?打死我也不信Top
12 楼jy(树,路)回复于 2001-05-24 10:49:00 得分 0
"这本书上几乎全是这样使用"是怎么个用法?贴来看看。
“在程序中将两种写法都用了一下,效果居然一样。真是奇怪,难道1)、2)两种写法等价?”是指
“pb->operator->()->func1(); 还是 2)pb->operator->func1();”?
我怀疑,因为2)连编译都不能,也不应该通过。Top
13 楼coolxiao(coolxiao)回复于 2001-05-24 13:02:00 得分 0
我看过关于smart pointer的那篇文章,其中有一句“Therefore, SIDraw–>Draw() from the previous examples results in a call to SIDraw.m_pI->Draw(). SIDraw delegates the Draw call to the interface pointed to by m_pI. ”为什么
SIDraw->Draw()会等价于SIDraw.m_pI->Draw(),而->的重载定义是返回一个指针啊,要是没有看过这篇文章的话,我会用(SIDraw->)->fun(),但是不能通过编译的,难道这是C++的特殊规则吗?Top
14 楼jy(树,路)回复于 2001-05-24 13:07:00 得分 0
原来全都还没明白!!!
你如果真的想使用smart机制,应该这样:
CB b(pa);
b->func1(); //b不是指针类型,而是CB对象的实例!!但是可以象指针一样工作,因为CB被进行了->重载
///////////////////////////////////////////////////////////
是的,b是一个对象,而不是真正的指针;
把b当作一个指针来使用,正是重载->的目的。
这样,才体现出C++之强大:紧凑,直观(在理解的基础上,这是直观的)。试想焉能不为之着魔?
Top
15 楼jy(树,路)回复于 2001-05-24 13:22:00 得分 0
->的重载,被解释为对象实例的类型转变。
同样通过重载进行转变的,还有!、(),例如
class a {
public:
bool operator !() { return false; }
bool operator () { return true; }
};
a A;
...
if(A){
}
if(!A){
}
Top
16 楼jy(树,路)回复于 2001-05-24 13:24:00 得分 0
应该是bool operator ()() { return true; }
Top
17 楼coolxiao(coolxiao)回复于 2001-05-24 13:35:00 得分 0
=)不要说我顽固啊,不过我还想问一下,没错(A)确实是返回TRUE,!(A)返回FALSE,那么说b->是不是应该返回一个pointer呢?但为什么不能这样用?
Top
18 楼fresh_(fresh_)回复于 2001-05-24 14:00:00 得分 0
to jy
谢谢,请继续不厌其烦的替我们讲解清楚。
to coolxiao
终于有人有我一样的问题了。“那么说b->是不是应该返回一个pointer呢?”我正是想追问这个。Top
19 楼jy(树,路)回复于 2001-05-24 14:34:00 得分 0
...
说起来,返回是一个指针,没错;但是...
:)
我承认,我的能力有限,无法解释清楚,这是我没有出书的原因,:P
不可以->->,而是->或者->()->
这算不算是一种语感?
我觉得,看这个问题,是一种方法问题。
一定要精确表述的话,(b->是不是应该返回一个pointer)是错误的,你只能说,(b.operator->()返回一个指针),所以,早前我指出(b.oerator->())->func()的语法才是正确的。注意,我用括号限定了b.operator->()来加强你对它的认识。
b->根本不是一个完整的表达式,更加谈不上具有返回值了。
Top
20 楼kalling(kalling)回复于 2001-05-24 14:41:00 得分 20
实际的例子:
我正好在做word的控制,从一个type library导入了一个包装类_Application
如_Appliction word;
既可以用word.QueryInterface(),又可以用word->Documents();
这就是smart pointerTop
21 楼coolxiao(coolxiao)回复于 2001-05-24 16:03:00 得分 0
那就奇怪了,既然->是单目运算符,为什么 b->是错误的表达式呢?
这样说int a=1,b; b=a++;不也不成立吗?因为我对smart pointer没有深入的了解,只是从c++重载运算符的规则出发来想问题的,是不是我的理解有问题呢?
看来fresh_(fresh_)你要加点分了,毕竟jy(树)对付我们也很烦的了,是不?=)
如果帖子超过25个回复,那我再开一帖帮高手们加分,只求一个合理解释而已!Top
22 楼jy(树,路)回复于 2001-05-24 17:34:00 得分 0
应该说我黔驴技穷才对,呵呵。
coolxiao这么追究对我也有好处,我也可以认真思考一番。
我可没有对付的意思:)
那么,->是不是单目呢?
我早前的理解是从它的特性着手的,把它视为一种特例。因为->的功能是为了返回一个“指针性质”的成员命名(Names),所以,尽管其后带有成员限定名,我们仍然当作是单目的运算符。
反过来,从operator语法上也可以反推这一点。
但,这当然不容易让人信服。
实际上如何呢?实际上,->没有目的概念,他既非单目,也非双目,。。
->在C++中是一种扩展的运算符,扩展表示这是一种类型转换运算符(type conversion operator)。【注:扩展理解见结尾的解释】
(好了,现在我资料在手,可不怕你们了)
在C++的手册里,->被分属成member-selection operator(正解!不是单目,不是双目,我就是我!),这和类型转换运算符的概念没有冲突,我是这么理解的。
好,再来,接着解释
其语法要求为:
postfix-expression :
primary-expression
postfix-expression [ expression ]
postfix-expression ( expression-listopt )
simple-type-name ( expression-listopt )
postfix-expression . name
postfix-expression -> name
postfix-expression ++
postfix-expression --
仔细研究这个语法表述,你可以明确的看出为什么b->不完整,a++却完整。
好了,收个尾:
我明确->operator的函数表达方法应该是:
operator type-name()
我强调把->理解为一个类型转换运算符(type conversion operator),这样,推而广之,你可以轻易写出一系列的运算符重载而不求人:
operator int ();
operator -> ();
operator char* ();
operator LPCTSTR ();
operator HWND ();
...
Top




