C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了C多重继承和Objective-C.这是GCC中的错误吗?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我昨天遇到了以下奇怪的行为.这对我来说似乎是一个编译器错误,还是有一些我错过的东西?我使用Objective-C到C适配器类将Facebook Connect for iPhone的Objective-C类包装起来,这样就可以更方便地使用我们自己的OpenGL / C代码.

以下代码显示了该问题.在下面的第一个变体中,编译器编译但是弄乱了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,请注明来意。