لا يمكن إجراء نسخ بناء دون إنشاء وظيفة صريحة في فئة القاعدة الافتراضية الخالصة؟

StackOverflow https://stackoverflow.com/questions/3813964

سؤال

هدفي هو القيام بنسخة عميقة من الفصل ، ولكن الفئة الافتراضية تسبب المتاعب.

#include<iostream>
using namespace std;

class Vir//pure virtual class
{
    public:
    virtual void hi()=0;
};

class Handler:public Vir
{
    public:
    int i;
    Handler() {}
    Handler(int val):i(val) {}
    void hi() {cout<<"Value of i="<<i<<endl;}
    int getI() const {return i;}
    void setI(int j) {i=j;}
};

class ControlPanel
{
    public:
    Vir *v;
    ControlPanel(const ControlPanel& c)//copy constructor
    {
        v=new Handler;
        v->setI(c.getI());
    }
    int getI()const {return v->getI();}

    void initialize() {v=new Handler(10);}
    void hi() {v->hi();}
    ControlPanel() {}
    ~ControlPanel() {delete v;}
};

int main()
{
    ControlPanel cc;
    cc.initialize();
    cc.hi();
    ControlPanel bb(cc);//copying cc into bb
}

رسالة خطأ التجميع:

test.cpp: In copy constructor ‘ControlPanel::ControlPanel(const ControlPanel&)’:
test.cpp:28: error: ‘class Vir’ has no member named ‘setI’
test.cpp: In member function ‘int ControlPanel::getI() const’:
test.cpp:30: error: ‘class Vir’ has no member named ‘getI’

أخطط للحصول على الكثير من فصول المعالج (مثل Handler1 ، Handler2 وما إلى ذلك) التي ترث من VIR وستكون لها أعضاء فريدين (مثل Float A ؛ أو Double B ؛ إلخ). لذلك ليس من المنطقي بالنسبة لي الحفاظ على جميع وظائف Getter & Setter لجميع فئات المعالج في فئة VIR. أريد أن أبقي أساليب getter و setter في فصول المعالج لأن الأعضاء فريدون في فصول المعالج. المترجم لا يسمح لي بالقيام بذلك. مساعدة؟

هل كانت مفيدة؟

المحلول

ربما أفتقد شيئًا ولكن ألا تكون أفضل مع افتراضي clone طريقة على Vir؟ هذا يعني أنه يمكنك تجنب المصبوب السيئ في ControlPanel نسخ مُنشئ في إجابتك الخاصة. هذا هو نفسه الذي يقترحه Andrew Aylett في إجابته مع duplicate يتم استخدامها بدلاً من clone.

شيء مثل

class Vir
{
    public:
    virtual Vir* clone() const = 0;
    ...
};

الذي يتم تنفيذه في Handler ان نكون

Handler* Handler::clone() const
{
    return new Handler( *this );
}

لاحظ استخدام نوع الإرجاع المتغير أي Handler::clone يسمح له بإعادة أ Handler* بدلا من مجرد أ Vir* وما زالت تجاوزًا صحيحًا Vir::clone.

هذا يجعل ControlPanel نسخ المنشئ ببساطة

ControlPanel( const ControlPanel& c )
    : v( c.v->clone() )
{
}

نصائح أخرى

أضف duplicate() الوظيفة إلى فئتك التجريدية ، والتي (في كل فئة مشتقة) تنشئ مثيلًا جديدًا مع القيم الصحيحة ويعيده. بدلا من ذلك ، النظر copyFrom(Abs other) الوظيفة التي تتحقق للتأكد من أنك تنسخ من النوع الصحيح ، وإذا كان الأمر كذلك ، فإن نسخ الحقول خارج.

بشكل عام ، إذا كانت فئة ControlPanel الخاصة بك لديها إشارة إلى كائن ABS ، فلا ينبغي أن تحاول القيام بازدواجها عن طريق فحص كائن المعالج الخرساني ، فيجب أن يمرر الازدواجية إلى وظيفة افتراضية على هذا الكائن.

لماذا يسمح لك المترجم؟ هذه الطرق ليست على تلك الواجهة.

يمكنك استخدام نمط المصنع لإنشاء الخاص بك Vir, ، لتجنب الاضطرار إلى إضافة جميع المُنشئين إلى Virواجهة. يجب عليك أيضًا التفكير في استخدام راي لتجنب تهيئة () وظائف النمط.

يتغيرون Vir *v ل Handler *v; ومعرفة ما إذا كان الرمز الخاص بك يجمع أم لا.

فصلك Vir لا يعلن/تحديد setI() و getI() وظائف الأعضاء.

أو تحديد Vir مثل

class Vir//pure virtual class
{
    public:
    virtual void hi()=0;
    virtual int getI()const =0;
    virtual void setI(int)=0;
};

عليك أن تحدد getI و setI كما (نقية) افتراضية في Vir لجعلها متاحة عبر الفئات الفرعية. بأي حال من الأحوال حول هذا.

كما اقترح ستيف ، أجب على سؤالي الخاص لأن صديقًا أعطاني حلاً. آمل أن يكون هذا مفيدًا لأي شخص لديه مسألة كيفية القيام بنسخة عميقة في C ++ حيث قد يكون الفصل الافتراضي حاجزًا. أملي أن يجد هذا نفعا.

#include<iostream>
using namespace std;

class Vir//pure virtual class
{
    public:
    virtual void hi()=0;
    virtual int getI() {std::cout << "Inside Base class" << std::endl;}
    virtual void setI(int i) {cout<<"In base"<<endl;}
    virtual int getX() {}
    virtual void setX(int x) {}
};
class Model
{
    public:
    int x;
    Model(const Model& mm) {x=mm.x;}
    Model():x(555) {cout<<"Model constructor called"<<endl;}
    int getX() {return x;}
    void setX(int xx) {x=xx;}
};

class Handler:public Vir
{
    public:
    int i;
    Model *m;

    Handler() {m=new Model;cout<<"Handler constructor called"<<endl;}
    Handler(const Handler& h)
    {
    std::cout << "Inside Handler @lineNumber:" << __LINE__ << std::endl;
    i=h.i;
    m=new Model(*h.m);
    }
    Handler(int val):i(val) {}
    ~Handler() {delete m;}
    void hi() {cout<<"Value of i="<<i<<endl;}
    int getI() {return i;}
    void setI(int j) {i=j;}
    int getX() {return m->getX();}
    void setX(int xx) {m->setX(xx);}
};

class ControlPanel
{
    public:
    int abc;
    Vir *v;
    ControlPanel(const ControlPanel& c)//copy constructor
    {
    std::cout << "Inside ControlPanel @lineNumber:" << __LINE__ << std::endl;
        v=new Handler((Handler&)*(c.v));
    }
    void initialize() {v=new Handler();v->setI(10);abc=222;}
    void hi() {v->hi();}
    ControlPanel() {}
    ~ControlPanel() {delete v;}
};

int main()
{
    ControlPanel cc;
    cc.initialize();
    cc.hi();    
    cout << "(cc.v)->i::" << (cc.v)->getI() << endl;
    cout<<"x value cc="<<(cc.v)->getX()<<endl;
    ControlPanel bb(cc);//copying cc into bb
    cout << "(bb.v)->i::" << (bb.v)->getI() << endl;
    cout<<"x value bb="<<(bb.v)->getX()<<endl;
    (cc.v)->setI(999);
    (cc.v)->setX(888888888);
    cout << "(cc.v)->i::" << (cc.v)->getI() << endl;
    cout << "(bb.v)->i::" << (bb.v)->getI() << endl;
    cout<<"x value cc="<<(cc.v)->getX()<<endl;
    cout<<"x value bb="<<(bb.v)->getX()<<endl;
}//main
/*
Output:
Model constructor called
Handler constructor called
Value of i=10
(cc.v)->i::10
x value cc=555
Inside ControlPanel @lineNumber:52
Inside Handler @lineNumber:32
(bb.v)->i::10
x value bb=555
(cc.v)->i::999
(bb.v)->i::10
x value cc=888888888
x value bb=555  */
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top