大佬教程收集整理的这篇文章主要介绍了C多重继承和Objective-C.这是GCC中的错误吗?,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
以下代码显示了该问题.在下面的第一个变体中,编译器编译但是弄乱了vtable,因此调用了错误的方法.在第二个变体中,我们得到一个编译器错误,表明gcc很混乱.
评论试图更详细地解释这种情况.
#include <iostream> #import <Foundation/Foundation.h> // An abstract C++ interface class foo_cpp { public: virtual void foo() = 0; }; // Another abstract C++ interface class Bar_cpp { public: virtual void bar() = 0; }; // An Objective-C to C++ adaptor. // It takes a C++ interface Foo. When it's do_foo method is called it // delegates call to Foo::foo. @interface foo_objc : NSObject { foo_cpP* foo_cpp_; } @end @implementation foo_objc - (id)init:(foo_cpP*)foo { self = [super init]; if (self) { foo_cpp_ = foo; } return self; } - (void) do_foo { std::cout << "do_foo: "; foo_cpp_->foo(); } @end // Another Objective-C to C++ adaptor. @interface Bar_objc : NSObject{ Bar_cpP* bar_cpp_; } @end @implementation Bar_objc - (id)init:(Bar_cpP*)bar { self = [super init]; if (self) { bar_cpp_ = bar; } return self; } - (void) do_bar { std::cout << "do_bar: "; bar_cpp_->bar(); } @end // Main class implements both abstract C++ interfaces (which will // confuse the compiler as we shall seE). // It constructs two Objective-C to C++ adaptors as a members and // tries to pass itself as a C++ delegate for these adaptors. class Main : public foo_cpp,public Bar_cpp { public: foo_objc* foo_; Bar_objc* bar_; Main() { // We try to construct two objective-c to c++ adaptors foo_objc and // Bar_objc. // // We expect output of // [foo_ do_foo]; // [bar_ do_bar]; // to be // do_foo: foo // do_bar: bar #if 0 // This variant compiles but the compiler messes up // the vtables. When do_bar() is called,we expect // bar() to be called via Bar_objc,but instead // foo() is called from both adaptors. // Output is // do_foo: foo // do_bar: foo !!!! Calls wrong method !!!! foo_ = [[foo_objc alloc] init:this]; bar_ = [[Bar_objc alloc] init:this]; [foo_ do_foo]; [bar_ do_bar]; #else // Now,this variant tries to Help the compiler by passing // |this| via a variable of the correct interface type. // It actually reveals the confusion that the compiler // is having. Seems like a bug in the compiler. foo_cpP* iface = this; foo_ = [[foo_objc alloc] init:iface]; Bar_cpP* iface2 = this; // Error we get is on the next code line. // $g++ -x objective-c++ -lobjc mheritance_test.mm // mheritance_test.mm: In constructor ‘Main::Main()’: // mheritance_test.mm:107: error: cAnnot convert ‘Bar_cpP*’ to ‘foo_cpP*’ in argument passing bar_ = [[Bar_objc alloc] init:iface2]; [foo_ do_foo]; [bar_ do_bar]; #endif } ~Main() { delete foo_; delete bar_; } virtual void foo() { std::cout << "foo" << std::endl; } virtual void bar() { std::cout << "bar" << std::endl; } }; int main() { Main m; }
iPhone SDK和Mac自己的版本以及4.0.1和4.2版本会出现此问题.
有没有我错误理解的东西或者这是g中的错误?
updatE
我的例子中包含一个偶然的错误指出泰勒和马丁约克,但这不是问题.以下是更新的示例.
#include <iostream> #import <Foundation/Foundation.h> // An abstract C++ interface class foo_cpp { public: virtual void foo() = 0; }; // Another abstract C++ interface class Bar_cpp { public: virtual void bar() = 0; }; // An Objective-C to C++ adaptor. // It takes a C++ interface Foo. When it's do_foo method is called it // delegates call to Foo::foo. @interface foo_objc : NSObject { foo_cpP* foo_cpp_; } @end @implementation foo_objc - (id)init:(foo_cpP*)foo { self = [super init]; if (self) { foo_cpp_ = foo; } return self; } - (void) do_foo { std::cout << "do_foo: "; foo_cpp_->foo(); } @end // Another Objective-C to C++ adaptor. @interface Bar_objc : NSObject{ Bar_cpP* bar_cpp_; } @end @implementation Bar_objc - (id)init:(Bar_cpP*)bar { self = [super init]; if (self) { bar_cpp_ = bar; } return self; } - (void) do_bar { std::cout << "do_bar: "; bar_cpp_->bar(); } @end class Main : public foo_cpp,public Bar_cpp { void foo() { std::cout << "foo" << std::endl; } void bar() { std::cout << "bar" << std::endl; } }; int main() { Main* m = new Main; #if 0 // Compiles but produces // do_foo: foo // do_bar: foo !!! incorrect method called !!! foo_objc* fo = [[foo_objc alloc] init:m]; Bar_objc* bo = [[Bar_objc alloc] init:m]; #else // Doesn't compile foo_objc* fo = [[foo_objc alloc] init:(foo_cpP*)m]; Bar_objc* bo = [[Bar_objc alloc] init:(Bar_cpP*)m]; // A line above produces following error // mheritance_test2.mm: In function ‘int main()’: // mheritance_test2.mm:82: error: cAnnot convert ‘Bar_cpP*’ to ‘foo_cpP*’ in argument passing #endif [fo do_foo]; [bo do_bar]; }
更新2
如果将init:Fooobjc和Barobjc的方法重命名为initfoo:和initbar:那么它可以正常工作,但我仍无法解释代码的问题.与Objective-C如何创建方法签名有关吗?
我不是一个Objective-C程序员,但是出于好奇心,我不禁想知道发生了什么,并且稍微使用了代码.我发现除了Foo *和Bar *部分并将以下行添加到main()后,问题浮出水面:
Bar_objc *bo = [[Bar_objc alloc] init:(Bar_cpP*)0];
玩了一下之后我发现它必须与未完全定义的alloc消息结果有关.通过将上面的分配分成两部分来解决这个问题:
Bar_objc *bo = [Bar_objc alloc]; [bo init:(Bar_cpP*)0];
这很好用.那么转换alloc结果(参见下面的代码).或者,这可以修复(我相信)具有不同的初始化器名称.也许还重新实现了alloc.不知道.
具有多重继承的完整代码(它还有一些其他的小改动 – 为了简洁,我将类/公共对更改为结构,删除了在构造函数中调用虚拟,将删除调用更改为dealloc消息,可能还有其他@L_944_54@):
#include <iostream> #import <Foundation/Foundation.h> struct foo_cpp { virtual void foo() = 0; }; struct Bar_cpp { virtual void bar() = 0; }; @interface foo_objc : NSObject { foo_cpP* foo_cpp_; } - (id)init:(foo_cpP*)foo; - (void)do_foo; @end @implementation foo_objc : NSObject { foo_cpP* foo_cpp_; } - (id)init:(foo_cpP*)foo { if( self = [super init] ) foo_cpp_ = foo; return self; } - (void) do_foo { std::cout << "do_foo: "; foo_cpp_->foo(); } @end @interface Bar_objc : NSObject { Bar_cpP* bar_cpp_; } - (id)init:(Bar_cpP*)bar; - (void)do_bar; @end @implementation Bar_objc : NSObject { Bar_cpP* bar_cpp_; } - (id)init:(Bar_cpP*)bar { if( self = [super init] ) bar_cpp_ = bar; return self; } - (void) do_bar { std::cout << "do_bar: "; bar_cpp_->bar(); } @end struct Main : public foo_cpp,public Bar_cpp { foo_objc* foo_; Bar_objc* bar_; Main() { foo_ = [(foo_objc*)[foo_objc alloc] init:this]; bar_ = [(Bar_objc*)[Bar_objc alloc] init:this]; } ~Main() { [foo_ dealloc]; [bar_ dealloc]; } virtual void foo() { std::cout << "foo" << std::endl; } virtual void bar() { std::cout << "bar" << std::endl; } }; int main() { Main m; [m.foo_ do_foo]; [m.bar_ do_bar]; }
结果:
do_foo: foo do_bar: bar
底线:我认为由于键入有点弱,并且无论类型如何都可以向对象发送消息,最好不要使用相同名称但不同参数的消息.
以上是大佬教程为你收集整理的C多重继承和Objective-C.这是GCC中的错误吗?全部内容,希望文章能够帮你解决C多重继承和Objective-C.这是GCC中的错误吗?所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。