我想为我的一个类编写一个构造函数,它在一组预定义的参数之后获取可变数量的std::string
个参数。
我目前的代码如下:
// Audio.h
#include <string>
class Audio {
public:
Audio(std::string title, std::string author);
protected:
std::string title, author;
}
// Song.h
#include "Audio.h"
class Song : public Audio {
public:
Song(std::string title, std::string artist) : Audio(title, artist);
// I have working code to populate mFeatures from features
Song(std::string title, std::string artist, std::string *features)
: Audio(title, artist);
private:
std::string *mFeatures;
}
所以我有一个带string, string
的构造函数和一个带string, string, *string
的构造函数。我想写一个用string, string
后跟任意数量的字符串来填充mFeatures
。
我环顾四周,找到this question和this question,其中列出了成员函数的想法,但我没有找到与构造函数相关的答案。
string
参数后跟任意数量的string
个参数?答案 0 :(得分:2)
执行此操作的最佳方法是使用初始化列表。
// Song.h
#include "Audio.h"
class Song : public Audio {
public:
Song(std::string title, std::string artist, std::initializer_list<std::string> features) : Audio(title, artist), mFeatures(features) {};
private:
std::vector<std::string> mFeatures;
};
用法:
Song s("title", "artist", {"f1", "f2"});
他们可以迭代。更多信息请访问:http://en.cppreference.com/w/cpp/utility/initializer_list。此外,您不应该按值传递title
和artist
(除非您想了解std::move
),请通过const引用传递它们。
不要使用指向std::string
的指针来保持动态字符串数组;你可能会以这种方式泄漏内存,还有其他各种问题。只需使用vector
。
答案 1 :(得分:2)
尽管@NirFriedman的答案是正确的,但我不喜欢以下表格:
Song s("title", "artist", {"f1", "f2"});
我宁愿使用这样的表格:
Song s("title", "artist", "f1", "f2");
这几乎是相同的,但事实上你不必使用std::initializer_list
。
C ++ 17版本(参见wandbox):
#include<string>
#include<vector>
#include<type_traits>
class Audio {
public:
Audio(std::string title, std::string author)
: title{title}, author{author} {}
protected:
std::string title, author;
};
class Song : public Audio {
public:
template<typename... T>
Song(std::string title, std::string artist, T... features)
: Audio(title, artist), mFeatures{features...}
{
static_assert(std::conjunction_v<std::is_convertible<T, std::string>...>);
}
private:
std::vector<std::string> mFeatures;
};
int main() {
Song song{"foo", "bar", "..."};
}
C ++ 14替代方案(参见wandbox):
class Song : public Audio {
template<bool... B>
static constexpr bool check = std::is_same<
std::integer_sequence<bool, true, B...>,
std::integer_sequence<bool, B..., true>
>::value;
public:
template<typename... T>
Song(std::string title, std::string artist, T... features)
: Audio(title, artist), mFeatures{features...}
{
static_assert(check<std::is_convertible<T, std::string>::value...>, "!");
}
private:
std::vector<std::string> mFeatures;
};
static_assert
的优点是,它可以帮助在出现错误时打印更加用户友好的错误消息。请注意,在上面的示例中,分配mFeatures{features...}
也会给您一个错误。无论如何,您可以决定在构造函数体内详细说明features...
并在检测到不一致时立即停止编译
答案 2 :(得分:0)
模板也可以在构造函数上工作,并且通过扩展也可以使用可变参数模板。如果你已经尝试过它并且它不起作用,请检查你是如何编译它的。
答案 3 :(得分:0)
您应该传递字符串,字符串,然后传递字符串向量。在向量中存储任意数量的字符串。这可能是解决这个问题的最好方法。
答案 4 :(得分:0)
template <typename ...List>
Song(const std::string& title, const std::string& artist, List&&... features) : Audio(title, artist)
然后只使用特征形式作为私有成员函数的参数,该函数设置特征成员就像您链接的示例一样。您链接的那个主题中的最佳答案也适用于您。