繁体   English   中英

根据另一个成员参数将函数调用从一个类传递给它的一个成员

[英]Pass function call from a class to one of its members based on another member parameter

假设我有以下class 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 
}

现在出于某种原因,我需要相同的类,但具有双向量。 我无法对此类进行模板化,因为有许多我无法更改的函数签名。 建议是将A重命名为A0 ,对其进行模板化,创建包含A0<int>A0<double>A ,如下所示:

template <typename T>
class A0{
std::vector<T> a;
public:
int getSize const {return a.size();}
T getVal(int i) const {return a[i];}
// other private and public members and functions 
}

class A{
// only one of the following will be initialized in the constructor and the other one will be null.
std::shared_ptr<A0<int>> iA;
std::shared_ptr<A0<double>> dA;
// also the following flag will be set in the constructor
bool isInt;
}

这就是问题所在:如果我想在以前访问、更改或仅传递A类实例的代码的不同位置进行最小更改,应该怎么做? 例如,在旧代码的不同部分考虑这一点:

A x;
int n = x.getSize();

有没有办法保留旧代码而不在新A类中实现方法getSize() ,该方法将包含 if 条件语句并基于isInt返回iA->getSize()dA->getSize() 有没有聪明的方法来做到这一点?

是否有任何其他建议可以在使用(主要是传递)旧A的代码的不同部分中实现最小修改的目标?

}

std::variant可能正是您所需要的。 创建一个buffer类并将所有容器操作转发给它。 没有必要在你的类A改变太多,但你应该在buffer模仿std::vector<T> ,我实现了size()const subscript operator 这里是基本演示。

#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;
}

输出 :

我将数字存储为 int
我将数字存储为双倍
0
0

在线运行

如果这只是关于传递对象(或对它的引用)而不是实际使用对象的任何成员,那么您可以简单地使用std::variant

using A = std::variant<A0<int>, A0<double>>;

在实际使用成员时,使用std::visit确定类型并对其进行操作。


如果仅通过引用进行传递,则使A成为A0<T>的空基类也将起作用。 然后,您可以使用static_cast<A0<int>&>(...)static_cast<A0<double>&>(...)转换回真实类型以使用目的地的成员。 但是,您必须确保转换为传递对象的实际类型,否则您将具有未定义的行为。

另一种选择是dynamic_cast而不是static_cast ,如果类型不匹配,它将抛出或返回空指针。 但这需要基类A有一个虚方法是多态的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM