2014-02-21 19 views
1

我在接口,继承和重定义方面遇到了一些问题。在这种情况下,我不确定为什么C++的行为如此,所以如果有人能够解释和帮助我。我有这个类:C++:继承函数并重新定义它们

module.h中:

class mixer; 

class module { 

public: 

    module(std::string name_) : name(name_) {} 
    ~module() {} 

    virtual module& bind(module &mod) = 0; 
    virtual module& bind(mixer &mix) { return ((module&)mix); } 

    std::string get_name() 
    { 
    return name; 
    } 

    std::string name; 
}; 

in_out.h:

class in_out : public module { 

public: 

    in_out(std::string name_) : module(name_) {} 
    ~in_out() {} 

    virtual module& bind(module &mod) 
    { 
    std::cout << "bind in_out in " << mod.name << std::endl; 
    return mod; 
    } 

}; 

prod.h:

class prod : public in_out { 

public: 

    prod(std::string name_) 
    : in_out(name_) 
    {} 

    ~prod() {} 

    virtual module& bind(mixer &mix) 
    { 
    std::cout << "bind mixer in " << get_name() << std::endl; 
    return mix; 
    } 

}; 

mixer.h:

class mixer : public in_out { 

public: 

    mixer(std::string name_) 
    : in_out(name_) 
    {} 

    ~mixer() {} 
}; 

所以,如果在我的主文件,我有这样的:

int main(int argc, char *argv[]) 
{ 
    prod prod1("prod1"); 
    prod prod2("prod2"); 
    mixer mixer1("mixer1"); 
    mixer mixer2("mixer2"); 

    prod1.bind(prod2); 

    return 0; 
} 

我得到这个错误:

main.cpp: In function ‘int main(int, char**)’: 
main.cpp:12:19: error: no matching function for call to ‘prod::bind(prod&)’ 
main.cpp:12:19: note: candidate is: 
prod.h:19:23: note: virtual pfn_module& prod::bind(mixer&) 
prod.h:19:23: note: no known conversion for argument 1 from ‘prod’ to ‘mixer&’ 
make: *** [main] Error 1 

如果我有这个:

prod1.in_out::bind(prod2); 

它按预期工作。

我不明白的是,编译器不应该区分这些吗?

virtual module& bind(module &mod) = 0; 
// and 
virtual module& bind(mixer &mix) { return ((module&)mix); } 

我想这个问题可能是双方mixerprodmodule(和in_out)的孩子。也许当函数bind在main中被调用时,它会在prod的定义中寻找它,并且只能找到bind(mixer)?那么bind(module)?在这种情况下它是私密的吗?

我想吃点什么的,不管是什么我打电话prod.bind(prod)prod.bind(mixer),它在prod的水平区分开来,所以我没有打电话给.in_out从那里。

感谢很多:)

回答

3

的问题是,当你在类范围内定义的类督促和声明的函数绑定

virtual module& bind(mixer &mix); 

你墙根所有其它功能与基类同名。所以你叫

prod1.bind(prod2); 

编译器在类作用域中只看到一个候选者:上面显示的函数。它不能将参考产品转换为参考混合器。

你应该在类定义

using in_out::bind; 

写信和@Alex在他的评论中指出,你必须让类模块虚拟的析构函数,如果你使用多态。

编辑:如果替代pfn_inout为IN_OUT因为没有pfn_inout的定义然后将以下代码表被成功

#include <iostream> 
#include <string> 

class mixer; 

class module { 

public: 

    module(std::string name_) : name(name_) {} 
    ~module() {} 

    virtual module& bind(module &mod) = 0; 
    virtual module& bind(mixer &mix) { return ((module&)mix); } 

    std::string get_name() 
    { 
    return name; 
    } 

    std::string name; 
}; 

class in_out : public module { 

public: 

    in_out(std::string name_) : module(name_) {} 
    ~in_out() {} 

    virtual module& bind(module &mod) 
    { 
    std::cout << "bind in_out in " << mod.name << std::endl; 
    return mod; 
    } 

}; 

class mixer : public in_out { 

public: 

    mixer(std::string name_) 
    : in_out(name_) 
    {} 

    ~mixer() {} 
}; 

class prod : public in_out { 

public: 
    using in_out::bind; 

    prod(std::string name_) 
    : in_out(name_) 
    {} 

    ~prod() {} 

    virtual module& bind(mixer &mix) 
    { 
    std::cout << "bind mixer in " << get_name() << std::endl; 
    return mix; 
    } 

}; 


int main() 
{ 
    prod prod1("prod1"); 
    prod prod2("prod2"); 
    mixer mixer1("mixer1"); 
    mixer mixer2("mixer2"); 

    prod1.bind(prod2); 

    return 0; 
} 
+1

也做了基类的析构函数是虚拟的。 –

+0

@Alex你说得对。谢谢,我会追加我的文章。 –

+0

好的。使得很多SENCE的:)但我发现了这个错误: '错误:“虚拟模块和IN_OUT ::绑定(模块&)”是inaccessible' – makeMonday

1

在C++编译,名字查找在其中找到该名字的范围停止。 (有一些例外,链接到ADL,但它们在这里不适用 )。原因是为了避免更改派生函数的语义 如果将名称添加到基类 类。

通常,这不应该是一个问题,因为您应该在所有 派生类中的接口中实现所有虚拟函数。而虚拟功能和非虚拟功能不应该共享名称。在你的情况,你 可能希望在基类什么是一样的东西:

class Module 
{ 
private: 
    virtual Module& doBind(Module& mod) = 0; 

public 
    Module& bind(Module& mod) 
    { 
     // pre-conditions 
     Module& results = doBind(mod); 
     // post-conditions and invariants 
     return results; 
    } 
    Module& bind(Mixer& mix) 
    { 
     // pre-conditions 
     Module& results = doBind(static_cast<Module&>(mod)); 
     // post-conditions and invariants 
     return results; 
    } 
}; 

派生类将执行自己的doBind, 但没有别的版本。

但有一件事。当编译器看不到的Module完整定义的转换(Module&)mix,在上下文 , 是reinterpret_cast,这几乎肯定是什么 你想要的。在我的示例中,我使用static_cast来与 对齐,但事实上,如果编译器 无法看到Module的定义,它实际上是非法的。在这种特殊情况下,实际上,不需要第二个bind 函数,因为Mixer&将隐式转换为Module&, 而不需要您的部分进行转换。 (但它很可能 这个代码只是一个很简单的例子, 在你真正的代码,你实际上是在做一些更复杂的 )