C++ 如何初始化共享复杂初始化代码的多个常量成员变量? 介绍

C++ 如何初始化共享复杂初始化代码的多个常量成员变量? 介绍,c++,constructor,constants,member-initialization,C++,Constructor,Constants,Member Initialization,让我们介绍一个简单的例子: #include <cmath> class X { public: // Members /// A ^ B + A int A; /// A ^ B + B int B; public: // Specials X( const int & A, const int & B ) : A(A) , B(B) {

让我们介绍一个简单的例子:

#include <cmath>

class X
{
public: // Members

    /// A ^ B + A
    int A;

    /// A ^ B + B
    int B;

public: // Specials

    X(
        const int & A,
        const int & B
    )
        : A(A)
        , B(B)
    {
        const auto Pow = static_cast<int>(std::pow(A, B));

        this->A += Pow;
        this->B += Pow;
    }
};
创建struct Init,它扮演类X的旧版本的角色。 使X成员为常量,同时使Init成员为非常量。 使用构造函数委托将构造函数参数重定向到Init。 将非常量成员变量从Init移动到X,并使其成为常量。 注意,没有std::move as int。 然而,我的解决方案似乎过于复杂。任何帮助都将不胜感激

没有目标 创建另一个X成员变量,该变量将存储公共代码结果,即std::pow。 在X类之外添加另一个间接级别,例如为X引入基类。 笔记

解决方案可以使用比C++ 11更新的C++版本。

< P>可以通过使用工厂函数来解决这个问题。您将X的构造函数设为私有,然后使用友元/静态函数获取X的对象。然后您可以在函数体中执行复杂代码,然后将这些值传递给X的构造函数。这类似于

class X
{
public:
    const int A;
    const int B;
    friend X make_X(int a, int b)
    {
        // do complex stuff
        return X(complex_result1, complex_result2);
    }
    // or
    static X make(int a, int b)
    {
        // do complex stuff
        return X(complex_result1, complex_result2);
    }
private:
    X(const int  A, const int  B) : A(A), B(B) {}
};
而且会像这样使用

X foo = make_x(a, b);
//or
X foo = X::make(a, b);

您可以通过使用工厂函数来解决此问题。您将X的构造函数设为私有,然后使用友元/静态函数获取X的对象。然后您可以在函数体中执行复杂代码,然后将这些值传递给X的构造函数。这类似于

class X
{
public:
    const int A;
    const int B;
    friend X make_X(int a, int b)
    {
        // do complex stuff
        return X(complex_result1, complex_result2);
    }
    // or
    static X make(int a, int b)
    {
        // do complex stuff
        return X(complex_result1, complex_result2);
    }
private:
    X(const int  A, const int  B) : A(A), B(B) {}
};
而且会像这样使用

X foo = make_x(a, b);
//or
X foo = X::make(a, b);
对于此类情况,使用a是一个很好的选择

class X
{
   public: // Members

      /// A ^ B + A
      const int A;

      /// A ^ B + B
      const int B;

   public:

      X(int a, int b) : X(a, b, func1(a, b)) {}

   private:

      X(int a, int b, int c) : A(func2(a, b, c)), B(func3(a, b, c)) {}

      static int func1(int a, int b) { return std::pow(a,b); }
      static int func2(int a, int b, int c) { return (a + c); }
      static int func3(int a, int b, int c) { return (b + c); }
};
func1、func2和func3中的逻辑/计算可以根据需要简单或复杂。

对于此类情况,使用a是一个很好的选择

class X
{
   public: // Members

      /// A ^ B + A
      const int A;

      /// A ^ B + B
      const int B;

   public:

      X(int a, int b) : X(a, b, func1(a, b)) {}

   private:

      X(int a, int b, int c) : A(func2(a, b, c)), B(func3(a, b, c)) {}

      static int func1(int a, int b) { return std::pow(a,b); }
      static int func2(int a, int b, int c) { return (a + c); }
      static int func3(int a, int b, int c) { return (b + c); }
};


func1、func2和func3中的逻辑/计算可以是简单的,也可以是复杂的。

我觉得使用委托构造函数而不是友元函数会更简洁?您还可以将其设置为静态成员makeint,int,并编写X::makea,b而不是makexa,b@chtz是的。我已经补充了这一点。谢谢。@Borgeader我觉得你是对的。我越是看R Sahu的答案,我就越喜欢它。我觉得使用委托构造函数而不是友元函数会更干净?你也可以将其设置为静态成员makeint,int,并写入X::makea,b而不是makexa,b@chtz是的。我已经补充了这一点。谢谢。@Borgeader我觉得你是对的。我越是看R Sahu的答案,我就越喜欢它。你有没有考虑过让成员成为私有的、非常量的,并且只允许访问者?这是启用此类功能的正常方式。我希望使用const,因为我将存储这些值,直到程序退出(例如许多小时),而不是因为我不希望它们被编辑/可见,所以getter/setter不是我的目标。变量的持续时间将是类实例的持续时间,不管它们是常量还是非常量。您考虑过静态吗?另外,您是否考虑过可能没有启用C++11?当我放置Init init1,2时,您的代码对我来说运行良好;X xinit;std::cout在我的代码中会有很多此类的实例,所以静态的并不是一个选项。我的代码中有std::最新版本,现在它使用了许多C++17和一个C++20版本,所以我确实启用了C++11。顺便说一句,我的问题已经解决了,谢谢。你有没有考虑过让成员私有化,非常量化,只允许访问者?这是启用此类功能的正常方式。我希望使用const,因为我将存储这些值,直到程序退出(例如许多小时),而不是因为我不希望它们被编辑/可见,所以getter/setter不是我的目标。变量的持续时间将是类实例的持续时间,不管它们是常量还是非常量。您考虑过静态吗?另外,您是否考虑过可能没有启用C++11?当我放置Init init1,2时,您的代码对我来说运行良好;X xinit;std::cout在我的代码中会有很多此类的实例,所以静态的并不是一个选项。我的代码中有std::最新版本,现在它使用了许多C++17和一个C++20版本,所以我确实启用了C++11。顺便说一句,我的问题已经解决了,谢谢。这正是我错过的,谢谢:理由:虽然NathanOliver的答案也解决了问题,但它增加了使用不同名称来初始化类ie X::make而不仅仅是X的要求。我已将您的答案标记为解决方案,因为它没有添加此类要求。这正是我错过的,感谢:理由:虽然NathanOliver的答案也解决了这个问题,但它增加了使用不同名称来初始化类ie X::make的要求,而不仅仅是X。我已经将您的答案标记为解决方案,因为它没有添加此类要求。