首页 > 解决方案 > 有没有一种方法可以交换成员变量而无需在子构造函数中单独传递它们?

问题描述

我的课程如下:

class Base
{
    public:
        virtual int ReturnX()
        {
            return x;
        }

    private:
        int x = 5;
};

class Derived : public Base
{
    private:
        int x = 10;
};

和代码如下:

int main()
{
    std::unique_ptr<Base> b = std::make_unique<Derived>();

    std::cout << b->ReturnX() << std::endl;
}

我知道如果我重写ReturnXDerived那么基指针将正确使用正确的ReturnX但我如何让它使用正确的x值?我希望线路返回 10。

我不想只在构造函数中传递它的原因是我有很多(10+)多维std::arraysx并且将它们单独传递给构造函数非常乏味。

标签: c++classvirtual

解决方案


方案一:根据派生类提供的策略构造基类成员

这里,基类由基类提供策略。该策略基本上只包含返回成员初始值的函数。

class Base {
    int x;
    std::string y;
   public:
    struct DefaultPolicy {
        int getX() { 
            return 5;
        }
        std::string getY() {
            return "Hello"; 
        }
    }; 
    
    virtual int getX() {
        return x;
    }
    virtual std::string getY() {
        return y;
    }

    template<class Policy>
    Base(Policy&& p) 
      : x(p.getX())
      , y(p.getY())
    {}

    // By default, Base uses the DefaultPolicy
    Base() : Base(DefaultPolicy()) {}

    virtual~Base() = default; 
};

现在,我们可以编写一个使用给定策略的派生类:

class Derived : public Base {
    // This is our policy
    struct Policy {
        int getX() {
            return 10; 
        }
        std::string getY() {
            return "Hello, world!"; 
        }
    };

   public:
    Derived() : Base(Policy()) {}
};

解决方案 2:使 base 成为可通过虚函数访问成员的接口

在这里,我们有Base一个没有成员变量的抽象类:

class Base {
   protected:
    virtual int& x_() = 0; 
   public:
    virtual int getX() {
        return x_();
    }

    virtual ~Base() = default; 
};

然后,我们可以根据初始值和其他内容创建单独的派生类:

class Derived1 : Base {
    int x = 5;
   protected:
    int& x_() override {
        return x;
    }
};
class Derived2 : Base {
    int x = 10;
   protected:
    int& x_() override {
        return x;
    }
};

解决方案 3:使用默认构造函数参数

有可能做这样的事情吗?

class Base {
   protected:
    int x;
   public:    
    Base(int x_ = 5) : x(x_) {}

    virtual int getX() {
        return x;
    }
    virtual ~Base() = default; 
};

class Derived : public Base {
   public:
    Derived(int x_ = 10) : Base(x_) {}
};

当你使用它时,你不必x在创建时指定一个值Derived,它按预期工作:

int main() {
    std::unique_ptr<Base> b = std::make_unique<Derived>();

    // Prints 10
    std::cout << b->getX() << '\n';
}

推荐阅读