通过C+中的重载构造函数初始化未知类型的变量+; 来自一个主要的Python背景,我在C++中使用了一些类型的工作。
我试图通过几个重载构造函数之一初始化一个类变量,这些重载构造函数采用不同的类型作为参数。我已经读到,使用通过C+中的重载构造函数初始化未知类型的变量+; 来自一个主要的Python背景,我在C++中使用了一些类型的工作。,c++,constructor,initialization,overloading,auto,C++,Constructor,Initialization,Overloading,Auto,我试图通过几个重载构造函数之一初始化一个类变量,这些重载构造函数采用不同的类型作为参数。我已经读到,使用auto关键字可以用于变量的自动声明,但是在我的情况下,在选择构造函数之前,它不会被初始化。但是,编译器不喜欢不初始化值 class Token { public: auto value; Token(int ivalue) { value = ivalue; } Token(float fvalue) { value = f
auto
关键字可以用于变量的自动声明,但是在我的情况下,在选择构造函数之前,它不会被初始化。但是,编译器不喜欢不初始化值
class Token {
public:
auto value;
Token(int ivalue) {
value = ivalue;
}
Token(float fvalue) {
value = fvalue;
}
Token(std::string svalue) {
value = svalue;
}
void printValue() {
std::cout << "The token value is: " << value << std::endl;
}
};
在这种情况下,使用auto
关键字的正确方法是什么?我应该使用完全不同的方法吗
通过C中的重载构造函数初始化未知类型的变量++
< C++ >中没有“未知类型变量”之类的东西。
在这种情况下,使用auto关键字的正确方法是什么
自动推导的变量具有从初始化器推导的类型。如果没有初始化器,则不能使用auto。auto不能用于非静态成员变量。类的一个实例不能具有与另一个实例不同类型的成员
在这种情况下,无法使用auto关键字
我应该使用完全不同的方法吗
可能吧。看起来您正在尝试实现一个std::variant
。如果您需要一个变量来存储X个类型中的一个,那么您应该使用这个变量
但是,您可能试图在C++中模拟动态类型。虽然您可能对Python很熟悉,但在许多情况下,这并不是理想的方法。例如,在这个特定的示例程序中,您对成员变量所做的就是打印它。因此,在每种情况下存储一个字符串会更简单。其他方法如Rhathin所示或Fire Lancer所示的OOP样式。
auto
必须可推断为特定类型,它不提供运行时动态类型
如果在声明Token
时,您知道可以使用的所有可能类型std::variant
等。这类似于使用“类型枚举”和“联合”。它确保调用正确的构造函数和析构函数
std::variant<int, std::string> v;
v = "example";
v.index(); // 1, a int would be 0
std::holds_alternative<std::string>(v); // true
std::holds_alternative<int>(v); // false
std::get<std::string>(v); // "example"
std::get<int>(v); // throws std::bad_variant_access
与其他人提出的不同的方法是使用模板。以下是一个例子:
template<class T>
class Token {
public:
T value;
Token(T value) :
value(std::move(value))
{}
void printValue() {
std::cout << "The token value is: " << value << std::endl;
}
};
模板
类令牌{
公众:
T值;
令牌(T值):
值(标准::移动(值))
{}
void printValue(){
std::cout您可以使用std::variant
类型。下面的代码显示了一种方法(但我不得不承认,它有点笨拙):
#包括
#包括
类令牌{
公众:
std::变量值;
代币(国际货币){
价值=价值;
}
令牌(浮点值){
价值=价值;
}
标记(标准::字符串值){
值=S值;
}
void printValue(){
开关(value.index()){
案例0:
std::coutC++是一个,意味着所有变量类型都是在运行前确定的。因此,auto
关键字与javascript中的var
关键字不同,后者是一种动态类型语言。auto
关键字通常用于指定不必要的复杂类型
您所寻找的可能是使用C++模板类来完成的,它允许创建不同类型的类的多个版本。
这段代码可能就是您要寻找的答案
template <typename T>
class Token {
private:
T value;
public:
Token(const T& ivalue) {
value = ivalue;
}
void printValue() {
std::cout << "The token value is: " << value << std::endl;
}
};
模板
类令牌{
私人:
T值;
公众:
代币(const T&ivalue){
价值=价值;
}
void printValue(){
std::cout下面的解决方案在精神上与Fire Lancer的答案中的解决方案类似。它的关键区别在于,它可能使用模板跟随注释,从而消除了显式创建接口派生实例的需要。Token
本身不是接口类。相反,它将接口定义为内部类类和一个内部模板类来自动定义派生类
它的定义似乎过于复杂。但是,Token::Base
定义了接口,Token::Impl
从接口派生。这些内部类对Token
的用户完全隐藏。用法如下:
class Token():
def __init__(self, value):
self.value = value
def printValue(self):
print("The token value is: %s" % self.value)
Token s = std::string("hello");
Token i = 7;
std::cout << "The token value is: " << s << '\n';
std::cout << "The token value is: " << i << '\n';
标记的定义如下所示
class Token {
struct Base {
virtual ~Base () = default;
virtual std::ostream & output (std::ostream &os) = 0;
};
template <typename T>
struct Impl : Base {
T val_;
Impl (T v) : val_(v) {}
operator T () { return val_; }
std::ostream & output (std::ostream &os) { return os << val_; }
};
mutable std::unique_ptr<Base> impl_;
public:
template <typename T>
Token (T v) : impl_(std::make_unique<Impl<T>>(v)) {}
template <typename T>
operator T () const { return dynamic_cast<Impl<T>&>(*impl_); }
friend auto & operator << (std::ostream &os, const Token &t) {
return t.impl_->output(os);
}
};
类令牌{
结构基{
virtual~Base()=默认值;
虚拟std::ostream&output(std::ostream&os)=0;
};
模板
结构Impl:基础{
T瓦卢;
Impl(tv):val_v{}
运算符T(){return val_;}
标准::ostream和输出(标准::ostream和操作系统){返回操作系统,我相信你不能使用<代码> Auto < C++ >类成员,相关但过时的问题:任何不使用模板的原因?Python,在运行时每种操作都确定类型,这需要开销,但是允许变量类型从一个语句变为下一个。o该代码可以编译-float和int具有不同的二进制布局,需要使用不同的汇编指令。如果您希望在运行时具有灵活性,则需要使用联合类型(如variant),该联合类型为每种类型选择包含有效代码的多个分支中的一个,从而增加性能开销。如果您希望保留int和float,则rsion是独立的,模板是你的朋友。最好使用std::visit
而不是switch
union
是一种容易出错的低级机制。variant
可能在内部使用它,使它的使用更安全。@wondra union本身并没有多大用处,因为它无法检查我使用的是哪个成员s当前处于活动状态。与非平凡类(具有自定义析构函数)一起使用(如std::string)也是非常痛苦的。我们需要的是一个带标记的联合。这是datastructu
Token s = std::string("hello");
Token i = 7;
std::cout << "The token value is: " << s << '\n';
std::cout << "The token value is: " << i << '\n';
int j = i; // Allowed
int k = s; // Throws std::bad_cast
class Token {
struct Base {
virtual ~Base () = default;
virtual std::ostream & output (std::ostream &os) = 0;
};
template <typename T>
struct Impl : Base {
T val_;
Impl (T v) : val_(v) {}
operator T () { return val_; }
std::ostream & output (std::ostream &os) { return os << val_; }
};
mutable std::unique_ptr<Base> impl_;
public:
template <typename T>
Token (T v) : impl_(std::make_unique<Impl<T>>(v)) {}
template <typename T>
operator T () const { return dynamic_cast<Impl<T>&>(*impl_); }
friend auto & operator << (std::ostream &os, const Token &t) {
return t.impl_->output(os);
}
};