在 C++ 中,是否可以使用未知数量的参数编写方法模板,并在重写定义中指定参数数?

In C++ is it possible to template a method with unknown amount of parameters, and specify the number of parameters in the override definition?

提问人:Rick 提问时间:10/5/2023 最后编辑:JL00001Rick 更新时间:10/5/2023 访问量:57

问:

我有两个类(BaseClass、DerrivedClass),我想在 BaseClass 中创建一个具有未定义数量参数的虚拟方法。参数的数量(如果有)应在方法的 DerrivedClasses 重写中定义。 BaseClass 定义可以是抽象的,也可以不是抽象的,但最好是抽象的。我想要这样做的原因是,我可以强制 BaseClass 的每个子类用它自己的唯一值覆盖定义。

这是可能的,还是只是一厢情愿的想法?

class BaseClass
{
    public:
        // I want to be able to override this method with as many parameters as the DerrivedClass desires, without having to make a version of it in BaseClass.
        virtual AssignValues() = 0;
}

class DerrivedClass : public BaseClass
{
    public:
        void AssignValues(const std::string& value1, const int value2) override
        {
            m_value1 = value1;
            m_value2 = value2;
        };
    private:
        std::string m_value1;
        int m_value2;
}

class DerrivedClass2 : public BaseClass
{
    public:
        void AssignValues(const int value) override
        {
            m_value = value;
        };
    private:
        int m_value;
}

主 .cpp

DerrivedClass example1;
DerrivedClass2 example2;

example1.AssignValues("Test Name", 1);
example2.AssignValues(2);
C++ 方法 参数

评论

1赞 jjramsey 10/5/2023
这种方法的意义何在?通常,继承的要点是实现多态性,即代码应该能够处理相同的任何子类,而不知道它是还是在引擎盖下。如果他们有不同的论点,就很难对待,也是一样的。BaseClassDerivedClassDerivedClass2DerivedClass::AssignValues()DerivedClass2::AssignValues()
1赞 Igor Tandetnik 10/5/2023
我@jjramsey。您的示例中没有任何内容甚至依赖于存在。显示一个示例用法,该用法依赖于以下事实:并且具有公共基类,如果它们不起作用,则将不起作用。当你试图构建这个例子时,我希望你会发现为什么你提议的安排没有意义。BaseClassDerrivedClassDerrivedClass2
0赞 Serge Ballesta 10/5/2023
更明确地说,您要做的不是预期的继承工作方式。句点。如果你设法找到了一种方法来编译这种反模式,你应该为维护噩梦做好准备......
0赞 Rick 10/5/2023
其目的是强制子类定义和重写虚函数 (AssignValues)。与单例类结合使用,这为定义线程安全模板化单例类提供了可能性,同时明确定义了变量赋值的需求。
0赞 Wutz 10/5/2023
然后抛出基类,让模板化的单例检查类型参数是否通过概念或 requires 子句定义了这样的方法。

答:

0赞 alagner 10/5/2023 #1

你试图实现的目标在我看来是一个设计缺陷,但如果真的需要,你能得到的最接近的是一个虚拟成员函数,它有一个能够携带所有需要的信息的单态参数。 在我的第一个示例中,我使用了 std::variant,因此需要预先知道类型。

#include<iostream>
#include <variant>


struct Vals
{
    int x{};
    char y{};
};

using SetterArgs = std::variant<Vals, double>;

struct Base
{
    virtual void setValues(const SetterArgs&) = 0;
    virtual ~Base() = default;
};


struct Der1 : Base
{
    int val1;
    char val2;

    void setValues(const SetterArgs& a) override
    {
        const auto& v = std::get<Vals>(a);
        val1 = v.x;
        val2 = v.y;
    }
};

struct Der2 : Base
{
    double val;

    void setValues(const SetterArgs& a) override
    {
        const auto& v = std::get<double>(a);
        val = v;
    }
};

int main()
{
    Der1 d1;
    static_cast<Base&>(d1).setValues(Vals{82, 'z'});
    std::cout << d1.val1 << ' ' << d1.val2 << '\n';

    Der2 d2;
    static_cast<Base&>(d2).setValues(3.14);
    std::cout << d2.val << '\n';
}

https://godbolt.org/z/eM9eYd8e3

std::any也可以在这里工作

#include <any>


struct Vals
{
    int x{};
    char y{};
};

struct Base
{
    virtual void setValues(const std::any&) = 0;
    virtual ~Base() = default;
};


struct Der1 : Base
{
    int val1;
    char val2;

    void setValues(const std::any& a) override
    {
        const auto& v = std::any_cast<Vals>(a);
        val1 = v.x;
        val2 = v.y;
    }
};

struct Der2 : Base
{
    double val;

    void setValues(const std::any& a) override
    {
        const auto& v = std::any_cast<double>(a);
        val = v;
    }
};

https://godbolt.org/z/cGWY4h3qY

评论

0赞 billz 10/5/2023
修补有缺陷的设计从来都不是一个好的选择