【问题标题】:Maintaining a selected object in C++在 C++ 中维护选定的对象
【发布时间】:2021-10-26 11:00:51
【问题描述】:

为了更清楚,我想知道存储对所选对象的引用的最佳方法:

#include <iostream>
using namespace std;

class A{
    public:
    int a;
    A(int b)
    {
        a=b;
    }
};
class B{
    public:
    int b;
    B(int a)
    {
        b=a;
    }
};
int main() {
    A a(1);
    B b(2);
    **<<some type>>** x= &a;
    //cout<<x.a or x->a<<endl;
    x = &b;
    //cout<<x.b or x->b;
    return 0;
}

用例: 实际上,我正在解析一些格式化的字符串并返回解析的对象(类,A,B 作为回报)。在解析字符串时,我知道要填充什么对象以及要填充什么字段,以保存这些信息(在运行时更改)我正在寻找解决方案。这基本上为我节省了一个 switch case,并且应用程序对延迟敏感。

【问题讨论】:

  • 没有。不可能。 C++ 没有这个能力。
  • @user253751 它有 2 个 std::variantstd::any
  • @AlanBirtles 但是你仍然不能做 xb 或 x->b,你仍然必须做 std::get(x).b 这需要你知道类型是B.
  • “这基本上为我节省了一个 switch case,并且应用程序对延迟敏感”这是一个教师前提(减少一个 switch case 是目标)。因为类型在运行时是已知的,所以你总是要付出代价,无论是 switch case、vtable 间接(虚拟类)还是代码大小增加(重载)和隐藏分支(std::variant)。
  • @bolov 绝对,我明白,因此我希望获得尽可能低的成本,有什么建议吗?

标签: c++ class object pointers reference


【解决方案1】:

在我看来,所描述的用例就像一个抽象工厂模式。你解析一些东西,然后用一些设置的参数返回适当的类型。类型的决定将在运行时做出。通过使用多态性,您可以根据需要创建输出。

抽象工厂的标准问题是构造函数的签名必须相同。

但是使用下面显示的解决方案,您可以解析任何内容,然后实例化适当的类型并根据需要添加参数值。

请检查:

#include <iostream>
#include <map>
#include <utility>
#include <any>


// Some demo classes ----------------------------------------------------------------------------------
struct Base {
    Base(int d) : data(d) {};
    virtual ~Base() { std::cout << "Destructor Base\n"; }
    virtual void print() { std::cout << "Print Base\n"; }
    int data{};
};
struct Child1 : public Base {
    Child1(int d, std::string s) : Base(d) { std::cout << "Constructor Child1 " << d << " " << s << "\n"; }
    virtual ~Child1() { std::cout << "Destructor Child1\n"; }
    virtual void print() { std::cout << "Print Child1: " << data << "\n"; }
};
struct Child2 : public Base {
    Child2(int d, char c, long l) : Base(d) { std::cout << "Constructor Child2 " << d << " " << c << " " << l << "\n"; }
    virtual ~Child2() { std::cout << "Destructor Child2\n"; }
    virtual void print() { std::cout << "Print Child2: " << data << "\n"; }
};
struct Child3 : public Base {
    Child3(int d, long l, char c, std::string s) : Base(d) { std::cout << "Constructor Child3 " << d << " " << l << " " << c << " " << s << "\n"; }
    virtual ~Child3() { std::cout << "Destructor Child3\n"; }
    virtual void print() { std::cout << "Print Child3: " << data << "\n"; }
};



using UPTRB = std::unique_ptr<Base>;


template <class Child, typename ...Args>
UPTRB createClass(Args...args) { return std::make_unique<Child>(args...); }

// The Factory ----------------------------------------------------------------------------------------
template <class Key, class Object>
class Factory
{
    std::map<Key, std::any> selector;
public:
    Factory() : selector() {}
    Factory(std::initializer_list<std::pair<const Key, std::any>> il) : selector(il) {}

    template<typename Function>
    void add(Key key, Function&& someFunction) { selector[key] = std::any(someFunction); };

    template <typename ... Args>
    Object create(Key key, Args ... args) {
        if (selector.find(key) != selector.end()) {
            return std::any_cast<std::add_pointer_t<Object(Args ...)>>(selector[key])(args...);
        }
        else return nullptr;
    }
};

int main()
{
    Factory<int, UPTRB> factory{
        {1, createClass<Child1, int, std::string>},
        {2, createClass<Child2, int, char, long>}
    };
    factory.add(3, createClass<Child3, int, long, char, std::string>);


    // Some test values
    std::string s1(" Hello1 "); std::string s3(" Hello3 ");
    int i = 1;  const int ci = 1;   int& ri = i;    const int& cri = i;   int&& rri = 1;

    UPTRB b1 = factory.create(1, 1, s1);
    UPTRB b2 = factory.create(2, 2, '2', 2L);
    UPTRB b3 = factory.create(3, 3, 3L, '3', s3);

    b1->print();
    b2->print();
    b3->print();
    b1 = factory.create(2, 4, '4', 4L);
    b1->print();
    return 0;
}

如果答案不合适,请告知我,我将删除。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-07
    • 2010-11-10
    • 1970-01-01
    相关资源
    最近更新 更多