C++:使用基类实例的(副本)创建派生类的实例

C++ : create instance of derived class with a (copy of) an instance of a base class

提问人:Charles 提问时间:2/22/2023 最后编辑:Charles 更新时间:2/22/2023 访问量:66

问:

我看过很多与此相关的话题,但没有一个可以帮助我。

我有继承自 的类,就内部代码而言,我无法修改它(我不能去那里实现 copy-ctor,也不知道它的属性或任何东西的详尽列表)。BA

我得到了一个实例。我想创建一个实例,该实例具有所有已有的数据(实际上只是覆盖一个方法,仅此而已)。有什么方法可以做到这一点?ABA

更具体地说:我想对带有 a 的子类化并覆盖该方法(因为我认为它不接受该事件,这会阻止其他父小部件看到它 - 这是我想要的:接受并消费 ,做已经用它做的事情,即滚动选项卡,没有其他任何地方)。QTabBarQTabWidgetwheelEventQTabBarwheelEventQTabBar

但是我使用的是Qt Designer,所以它已经作为我放置在设计器中的一部分而创建,并且它具有我通过Designer设置的所有选项卡和属性。我可以稍后在代码中使用 替换它的方法,但是我希望我的自定义选项卡栏包含现有选项卡栏从最初放置在设计器中的自动生成中获取的所有数据。QTabBarQTabWidgetsetTabBarQTabWidgetQTabWidget

出于某种原因,Qt还强制禁用了其大部分或所有类的复制构造函数。因此,我不确定如何使用父类的现有实例轻松构建自定义选项卡栏QTabBar

此外,Qt Designer中也不可用,否则我会右键单击它并说“提升到<我的>子类”。如果你在设计器中点击,你得到的是你放置的QTabWidget,它有这个。很公平——但这条大道对我来说被封锁了。QTaskBarQTtabBarQTaskBarQTabBar

不管具体的Qt用例是什么(尽管我也对它非常感兴趣),我对一般问题的答案很感兴趣。但我担心这或多或少超出了C++的范围。

C++ Qt 继承复制 构造函数

评论

0赞 Charles 2/22/2023
我会编辑,但编辑队列已满。只是说 Qt Designer 中也不可用,否则我会右键单击它并说“提升到<我的 QTtabBar 子类>”。如果你在设计器中点击,你得到的就是你放置的,它有这个.很公平——但这条大道对我来说被封锁了。QTaskBarQTaskBarQTabWidgetQTabBar
1赞 pptaszni 2/22/2023
最简单的解决方案可能是将 Designer 逻辑移动到 cpp 中,然后像您计划的那样使用子类。QTabWidget
1赞 Charles 2/22/2023
我考虑过,但这可能会从几个人的脚下拉地毯。但这是可行的,长期的。特别是如果只拉动必要的最低量。但它仍然相当多。

答:

1赞 Petr 2/22/2023 #1

不完全了解Qt,但根据类层次结构,您可以查看装饰器模式。如果你有一个抽象的类接口,它会效果最好。A

class Ainterface {
public:
    Ainterface () {}
    Ainterface (const Ainterface &) = delete;
    Ainterface & operator=(const Ainterface &) = delete;
    Ainterface (Ainterface &&) = default;
    Ainterface & operator=(Ainterface &&) = default;
    virtual ~Ainterface () = default;

    virtual void foo() = 0;
    virtual void bar() = 0;
    // more methods
};

class A: public Ainterface {
    /* ... */
};

创建具有重写的类 B,如下所示:foo

class B: public Ainterface {
public:
    B(std::unique_ptr<Ainterface> a): a_(std::move(a)) {}
    void foo() override { /* your overridden code here */ }
    void bar() override { a_->bar(); }
    // more methods follow the pattern of `bar`
private:
    std::unique_ptr<Ainterface> a_;
};

如果没有抽象接口,另一种方法是让 的构造函数接受:ABA&&

class A {
public:
    A() {}
    A(const A&) = delete;
    A& operator=(const A&) = delete;
    A(A&&) = default;
    A& operator=(A&&) = default;
    virtual ~A() = default;

    virtual void foo();
    virtual void bar(); 
    // more methods
};

class B : public A {
public:
    B(A&& a): A(std::move(a)) {}
    void foo() override {}
};

...
A a;
B b(std::move(a));

评论

0赞 Charles 2/22/2023
这似乎仍然调用已删除的复制构造函数,在里面的某个地方。unique_ptr
0赞 Petr 2/22/2023
@Charles 最简单的例子编译正常:godbolt.org/z/b7Whhq1cq
0赞 Charles 2/22/2023
啊,你提供了一个新版本,好吧,这个我什至不能使用,因为 A 没有这样的接口 AFAIK,我无法修改它。
1赞 Petr 2/24/2023
@Charles,好吧,您要求一个通用的解决方案:)如果在Qt中你不能复制或移动类,那么我认为除了逐字节复制之外,没有任何方法,即使这样也会非常脆弱。
1赞 Charles 2/24/2023
是的,更多的阅读让我改变了对如何在Qt中解决我的问题的想法。 基本上,尝试复制大多数Qt对象是一个坏主意,因为有充分的理由。