在 C++ 中使用方法的参数列表

Use the list of arguments to a method in C++

这就是我想要做的 -- 我有一个 class A 和几个构造函数。我不想更改 class A 中的任何内容。我想要一个新的 class B,A 应该是 B 的一个元素,并且有一个镜像 A 的构造函数。

class A{
public:
   A(type1 arg1);
   A(type2 arg1, type3 arg2); 
}

我知道我能做到

class B{
A *a;
public:
   B(type1 arg1) {
      a = new A(arg1);
      //some other stuff here
   }
   B(type2 arg1, type3 arg2) {
      a = new A(arg1, arg2);
      //some other stuff here, same as the first constructor
   }
}

有办法吗?

class B{
A *a;
public:
   B(list_of_args) {
      a = new A(list_of_args);
      //some other stuff here
   }
}

我不想扩展 A。我只是在寻找一种方法来获取传递给 B 的参数列表并以此调用 A 的构造函数。 (不对 A 进行更改)。

使用 C++11 和可变参数模板,很容易:

class B {
    A a;

public:
    template <typename... Args>
    B(Args&&... args)
    : a(std::forward<Args>(args)...)
    { }
};

如果没有可变参数模板,您可以只为各种数量的参数添加一堆模板构造函数,但它非常难看。如果 none 的参数是引用,它不是 so bad

template <typename A1> 
B(const A1& a1) : a(a1) { }

template <typename A1, typename A2> 
B(const A1& a1, const A2& a2) : a(a1, a2) { }
// etc.

但实际上,您想要分别处理 A1&const A1&...因此您需要 2^N 个构造函数来处理 N 个参数。您可以看到为什么人们对 C++11 感到兴奋。

(请注意,在您的代码中,您有一个类型为 A 的 class 成员,但在您的构造函数示例中,您正试图创建一个 A*)。

您创建了一个模板化构造函数并使用了可变模板参数:

class B
{
public:
   template<typename... ArgTypes>
   B(ArgTypes... list_of_args) : a(list_of_args...)
   {
     //some other stuff here
   }
private:
  A a;
}

Live demo here.


如@Barry 的回答和评论中所述,最好使用 ArgTypes&&std::forward 以允许仅移动类型和一些效率。 Live demo here:

template<typename... ArgTypes>
B(ArgTypes&&... list_of_args) : a(std::forward<ArgTypes>(list_of_args)...)
{
  // do something here
}

我正在根据您的需求调整 Barry 的解决方案:

class A{
public:
   A(type1 arg1);
   A(type2 arg1, type3 arg2); 
}



class B{
A *a;
public:
   template <typename... Args>
   B(Args&&... args) {
      a = new A(std::forward<Args>(args)...);
      //some other stuff here
   }
}

另一种方法是为每个 B 构造函数声明一个要调用的成员方法来代替“//这里的其他一些东西”。

class B{
A *a;
public:
   void initialize(A* a) {
      this->a = a;
      //some other stuff here
   }

   B(type1 arg1) {
      initialize(new A(arg1));
   }

   B(type2 arg1, type3 arg2) {
      initialize(new A(arg1, arg2));
   }
}