如何选择调用的重载函数

Posted

技术标签:

【中文标题】如何选择调用的重载函数【英文标题】:How to choose the overloaded function called 【发布时间】:2019-03-30 14:57:34 【问题描述】:

我是 C++ 初学者,我想更改将在此代码中调用的函数版本:

#include <iostream>

class C1 ;

class C2 : public C1 ;

void func(C1 var) 
    std::cout << "Func 1" << std::endl;


void func(C2 var) 
    std::cout << "Func 2" << std::endl;


int main() 
    C1 *teste1 = new C1;
    C1 *teste2 = new C2;

    func(*teste1);                 // Want "Func 1"
    func(*teste2);                 // Want "Func 2"

    return 0;

从评论中可以看出,我想要的是当我取消引用指向 C2 类的指针时调用带有 C2 参数的 func。

编辑:只是为了澄清我真正想要实现的目标,下面的代码更接近我想要的:

#include <iostream>
#include <list>

class C1 ;

class C2 : public C1 ;

void func(C1 var) 
    std::cout << "Func 1" << std::endl;


void func(C2 var) 
    std::cout << "Func 2" << std::endl;


int main() 
    std::list<C1*> teste;

    teste.push_back(new C1);
    teste.push_back(new C2);

    // Want to print:
    // Func 1
    // Func 2
    for(auto i: teste) 
        func(*i);

    

    return 0;

【问题讨论】:

美丽的MCVE 和一个精彩的第一个问题。欢迎来到 ***!我希望看到更多像这样的问题! 你介意在这里找到一些有用的东西 - en.cppreference.com/w/cpp/experimental/constraints C++20。 【参考方案1】:

如果您知道自己正在处理 C2 对象,则可以先转换为 C2 指针:

func(*teste1);                   // Want "Func 1"
func(*static_cast<C2*>(teste2)); // Want "Func 2"

或者,您可以通过在C1 中拥有一个虚函数来使C2 具有多态性:

class C1 
public:
    virtual ~C1() 
;

然后你可以做一个dynamic_cast:

func(*dynamic_cast<C2*>(teste2)); // Want "Func 2"

请注意,如果您不确定自己拥有哪种对象,dynamic_cast 将在失败时返回一个空指针,因此您可以这样做:

if(dynamic_cast<C2*>(teste2)) 
    func(*dynamic_cast<C2*>(teste2)); //If it's a C2, call the C2 overload
 else 
    func(*teste2); //If it's a C1, call the C1 overload

或者更好的是,如果可以避免的话,根本不要使用指针!!

【讨论】:

或者从一开始就拥有正确类型的teste2 @SergeyA 好点,最后补充说(我觉得这是需要指针的更复杂的事情的一部分)。 感谢您的回答。我想这样做的原因是因为我有一个指向类 C1 的指针列表。我希望能够在 for 中执行 func 并选择正确的函数。我想使用指针的原因是因为这样我可以添加另一个类(我已经有 3 个类,如 C2),如果将来有必要,只需更改一两段代码。如果这不可能,我将不使用指针,并为每个类创建一个列表。 @Gusgo99 查看我的编辑。您可以使用dynamic_cast 来判断它实际指向的内容,并根据具体情况调用不同的内容。 @scohe001 谢谢,这正是我要找的!【参考方案2】:

如前所述,您可以使 func() 成为基类中的虚拟成员函数,然后覆盖它。然后调用 YourObject.func() 会返回你想要的。

虚拟函数具有查找 vtable 的开销,这在某些情况下会降低性能,但如果在编译时知道某物实际是哪种类型,则可以使用 CRTP 进行“静态多态性”。有很多关于这方面的文章,如果你走这条路,我建议你先学习模板——一定要先了解常规的虚函数。

【讨论】:

【参考方案3】:
#include <iostream>

class C1 
public:
    virtual void func()
        std::cout << "Func 1" << std::endl;
    
;

class C2 : public C1
public:
    void func() override
        std::cout << "Func 2" << std::endl;
    
;

int main() 
    C1* teste1 = new C1;
    C1* teste2 = new C2;

    teste1->func();                 // Want "Func 1"
    teste2->func();                 // Want "Func 2"

    return 0;

【讨论】:

谢谢你的回答,但问题是func是另一个类的成员函数,我不希望C1和C2访问这个第三类的一些成员变量。

以上是关于如何选择调用的重载函数的主要内容,如果未能解决你的问题,请参考以下文章

虚拟赋值运算符重载——如何选择正确的重载函数?

函数匹配

如何从基类中的函数调用重载函数?

根据条件选择重载函数

如何解决使用文字 0 和指针调用重载函数的歧义

通过函数名后加const重载的函数如何区分调用