C++ 基于另一个成员参数将函数调用从类传递给它的一个成员
假设我有下面的C++ 基于另一个成员参数将函数调用从类传递给它的一个成员,c++,class,templates,call,function-call,C++,Class,Templates,Call,Function Call,假设我有下面的类A,它通过不同的函数调用和包装器传递 class A{ std::vector<int> a; public: int getSize const {return a.size();} int getVal(int i) const {return a[i];} // other private and public members and functions } 这是一个问题:如果我想在以前访问、更改或刚刚传递classA实例的代码的不同位置进行最小更改,应该怎
类A
,它通过不同的函数调用和包装器传递
class A{
std::vector<int> a;
public:
int getSize const {return a.size();}
int getVal(int i) const {return a[i];}
// other private and public members and functions
}
这是一个问题:如果我想在以前访问、更改或刚刚传递classA
实例的代码的不同位置进行最小更改,应该怎么做?例如,在旧代码的不同部分中考虑这一点:
A x;
int n = x.getSize();
有没有一种方法可以不在新的a
类中实现方法getSize()
而保留旧代码,该类将包含if条件语句并基于isInt
返回iA->getSize()
或dA->getSize()
?有没有一个聪明的方法可以做到这一点
对于在使用旧A
的代码的不同部分中实现最小修改的目标,是否还有其他建议
}
std::variant
可能就是您所需要的。创建一个缓冲区
类并将所有容器操作转发给它。在类A
中不需要做太多更改,但应该在buffer
中模拟std::vector
,我实现了size()
和const subscript操作符
。这是基本的演示
#include <variant>
#include <vector>
#include <iostream>
struct store_as_int {};
struct store_as_double {};
class buffer {
public:
buffer( store_as_int ) : data { std::vector<int>{} } {
std::cout << "I am storing numbers as int" << std::endl;
}
buffer( store_as_double ) : data { std::vector<double>{} } {
std::cout << "I am storing numbers as double" << std::endl;
}
[[nodiscard]] std::size_t size() const noexcept {
std::size_t s;
std::visit( [ &s ]( auto&& arg ) {
s = arg.size();
} , data );
return s;
}
[[nodiscard]] double operator[]( std::size_t idx ) const {
double s;
std::visit( [ &s , idx ]( auto&& arg ) {
s = arg[ idx ];
} , data );
return s;
}
private:
std::variant< std::vector<int> , std::vector<double> > data;
};
class A{
buffer a;
public:
A() : a { store_as_int{} } {}
A( store_as_double ) : a { store_as_double {} } { }
int getSize() const { return a.size(); }
int getVal(int i) const { return a[i]; }
};
int main()
{
A x;
A y { store_as_double{} };
int n = x.getSize();
int t = x.getSize();
std::cout << n << std::endl;
std::cout << t << std::endl;
}
#包括
#包括
#包括
结构存储_as_int{};
结构存储为双{};
类缓冲区{
公众:
缓冲区(存储为int):数据{std::vector{}{
std::coutstd::variant
可能就是您所需要的。创建一个缓冲区
类并将所有容器操作转发给它。您的类a
中不需要做太多更改,但您应该在缓冲区
中模拟std::vector
,我实现了size()
和常量下标运算符
。以下是基本演示
#include <variant>
#include <vector>
#include <iostream>
struct store_as_int {};
struct store_as_double {};
class buffer {
public:
buffer( store_as_int ) : data { std::vector<int>{} } {
std::cout << "I am storing numbers as int" << std::endl;
}
buffer( store_as_double ) : data { std::vector<double>{} } {
std::cout << "I am storing numbers as double" << std::endl;
}
[[nodiscard]] std::size_t size() const noexcept {
std::size_t s;
std::visit( [ &s ]( auto&& arg ) {
s = arg.size();
} , data );
return s;
}
[[nodiscard]] double operator[]( std::size_t idx ) const {
double s;
std::visit( [ &s , idx ]( auto&& arg ) {
s = arg[ idx ];
} , data );
return s;
}
private:
std::variant< std::vector<int> , std::vector<double> > data;
};
class A{
buffer a;
public:
A() : a { store_as_int{} } {}
A( store_as_double ) : a { store_as_double {} } { }
int getSize() const { return a.size(); }
int getVal(int i) const { return a[i]; }
};
int main()
{
A x;
A y { store_as_double{} };
int n = x.getSize();
int t = x.getSize();
std::cout << n << std::endl;
std::cout << t << std::endl;
}
#包括
#包括
#包括
结构存储_as_int{};
结构存储为双{};
类缓冲区{
公众:
缓冲区(存储为int):数据{std::vector{}{
std::cout如果这只是关于传递对象(或对对象的引用)而不是实际使用对象的任何成员,那么您可以简单地使用std::variant
:
using A = std::variant<A0<int>, A0<double>>;
使用A=std::variant;
在实际使用成员时,使用std::visit
确定类型并对其进行操作
如果传递仅通过引用进行,则将A
设置为A0
的空基类也将起作用。然后,您可以使用static\u cast(…)
或static\u cast(…)强制转换回实际类型
使用目标位置的成员。但是,您必须确保强制转换为传递对象的实际类型,否则您将具有未定义的行为
另一种选择是dynamic\u cast
而不是static\u cast
,如果类型不匹配,它将抛出或返回空指针。但这要求基类a
具有多态的虚拟方法。如果这只是关于传递对象(或对对象的引用)并且不实际使用对象的任何成员,那么您只需使用std::variant
:
using A = std::variant<A0<int>, A0<double>>;
使用A=std::variant;
在实际使用成员时,使用std::visit
确定类型并对其进行操作
如果传递仅通过引用进行,则将A
设置为A0
的空基类也将起作用。然后,您可以使用static\u cast(…)
或static\u cast(…)强制转换回实际类型
使用目标位置的成员。但是,您必须确保强制转换为传递对象的实际类型,否则您将具有未定义的行为
另一种选择是dynamic\u cast
而不是static\u cast
,如果类型不匹配,它将抛出或返回空指针。但这要求基类a
具有多态的虚拟方法。您希望返回什么类型,例如getVal
,而不破坏依赖于i的先前代码t to beint
?当然这不是真正的代码,但在这种情况下,它会专门针对每种情况进行处理。大多数情况下,这个类只会从一个方法传递到另一个方法,直到它到达执行实际操作的方法(并且可以针对每种情况进行处理)您希望返回什么类型的代码,例如getVal
,而不破坏以前依赖它为int
的代码?当然,这不是真正的代码,但在这种情况下,它会针对每种情况专门处理。大多数情况下,该类只从一个方法传递到另一个方法,直到它到达执行实际操作的方法为止(每种情况下都可以处理)有没有可能为A0创建一个基类,而A0在A中使用?@KuroshMotamedian这里“used”是什么意思?不清楚你的问题的目的是什么。我的意思是A的成员是A0类型的共享指针。有可能吗?类A{B;//…};类B:public A{//…}@在我的两个建议中,A
都没有任何用户指定的成员。您是否混淆了A
和A0
?我的第二个建议假设A
是一个空基,因此派生的A0
可以作为A
的引用传递,但只能在static\u>转换后使用代码>返回到A0
。但是,这会发生(与第一个解决方案相反),目标预先知道传递的A&
是否真的引用了A0
或A0
。如果您将其转换为错误的,您将拥有UB。另一种选择是dynamic\u cast
,但A
必须是多态的,即具有虚拟func@KuroshMotamedian有关重要细节,请参见我答案中的更新ils,有可能吗