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 
}
这是一个问题:如果我想在以前访问、更改或刚刚传递class
A
实例的代码的不同位置进行最小更改,应该怎么做?例如,在旧代码的不同部分中考虑这一点:

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::cout
std::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 be
int
?当然这不是真正的代码,但在这种情况下,它会专门针对每种情况进行处理。大多数情况下,这个类只会从一个方法传递到另一个方法,直到它到达执行实际操作的方法(并且可以针对每种情况进行处理)您希望返回什么类型的代码,例如
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,有可能吗