简体   繁体   English

通过指向base,static_cast,crtp,删除模板的指针派生的成员

[英]Member of derived by pointer to base, static_cast, crtp, removing templates

Looking for: accessing member of a derived class from a pointer to base. 寻找:从指向基址的指针访问派生类的成员。

Reductio ad absurdum: 荒谬的还原:

class Base
{
public:
    int member_of_base;
};

class Derived : public Base
{
public:
    int member_of_derived;
};

I'm currently using templates: 我目前正在使用模板:

template <class T>
class Client
{
    T* data; // T is Base or Derived
};

There are few levels of composition in the class hierarchy, so I have to carry the template type parameter through all of the hierarchy. 类层次结构中的构成层次很少,因此我必须在所有层次结构中携带模板类型参数。 What is the best approach to overcome this? 克服此问题的最佳方法是什么? Obviously I cannot access the member of Derived via a pointer to Base, ie: 显然,我无法通过指向Base的指针来访问Derived的成员,即:

Base* foo = new Derived();
foo->member_of_derived; // no go

Thus, I'm using: 因此,我正在使用:

Client<Base>
Client<Derived>

I'm trying to come up with a solution that works without the templates. 我正在尝试提出一种无需模板即可使用的解决方案。 Options that I know would work: 我知道可以使用的选项:

  • void* //plain old C and casting as necessary, they're all pointers (as in memory addresses) in the machine void * // //替换旧的C并根据需要进行强制转换,它们都是机器中的指针(如在内存地址中)
  • static_cast<Derived*>(pointer_to_base); //type safe at compile time. //在编译时输入safe。
  • wrapping the cast in a Client's template method (not to be confused with a design pattern here) 将演员表包装在客户的模板方法中(不要在这里与设计模式混淆)

The last option seems to be the most "elegant", ie: 最后一个选项似乎是最“优雅”的,即:

template <class T>
T* get_data() const { return static_cast<T*>(data); }

However, looking here and there tells me there might exist a way unknown to me. 但是,四处看看告诉我可能存在一种未知的方法。 I saw CRTP, but that brings me back to templates, which is the original thing I want to go without. 我看到了CRTP,但是这使我回到了模板,这是我想要的原始东西。 What are the ways, or popular approaches, to achieve such a goal? 实现此目标的方法或流行方法是什么?

The real code uses shared_ptr, weak_ptr and enable_shared_from_this with weak_from_this. 实际的代码将shared_ptr,weak_ptr和enable_shared_from_this与weak_from_this一起使用。 I'm looking for a type safe "polymorphic member" access. 我正在寻找类型安全的“多态成员”访问权限。

EDIT: they're not just "ints". 编辑:他们不只是“整数”。 They can be totally different types, as in protobuf in base and Json::Value in derived. 它们可以是完全不同的类型,例如base中的protobuf和派生中的Json :: Value。 And I'm trying to use the pointers to Base/Derived, which in turn would give me access to their respective members. 而且我正在尝试使用指向Base / Derived的指针,这将使我能够访问它们各自的成员。

A virtual getter can solve the issue for you; 虚拟吸气剂可以为您解决问题; as data types differ, you might pack them into a std::variant . 由于数据类型不同,您可以将它们打包到std::variant

class Base
{
    // having private members probably is more appropriate
    int member_of_base;

public:
    using Data = std::variant<int, double>;

    virtual ~Base() { } // virtual functions -> have a virtual destructor!

    virtual Data getMember() // or just "member", if you prefer without prefix
    {
        return member_of_base;
    }
};

class Derived : public Base
{
    double member_of_derived;

public:   
    Data getMember() override
    {
        return member_of_derived;
    }
};

std::unique_ptr<Base> foo = new Base();
foo->getMember(); // member_of_base;
std::unique_ptr<Base> bar = new Derived();
bar->getMember(); // member_of_derived;

Admitted, not yet totally without templates, std::variant is one, but I suppose in that form it is acceptable... 承认,不是完全没有模板, std::variant是一个,但是我想以这种形式可以接受...

There are some issues with, though: 但是存在一些问题:

  1. Accessing the value is not the simplest, you might consider visit function for. 访问值不是最简单的,您可以考虑使用visit函数。
  2. More severe: Base class (or wherever else you define the variant to be used) needs to be aware of all types that might be in use, adding a new type will force to recompile all other classes. 更严重的是:基类(或您定义要使用的变体的任何其他地方)需要知道可能正在使用的所有类型,添加新类型将强制重新编译所有其他类。
  3. It has the smell of bad design. 它有不良设计的味道。 Why should it be necessary for a derived class to return something different than the base that shall serve the same purpose, though??? 为什么派生类必须返回与用于相同目的的基础不同的东西,但是呢?

If you can delegate the work to be done to the classes themselves, you get around all these problems: 如果可以将要完成的工作委托给类本身,则可以解决所有这些问题:

class Base
{
    int member_of_base;

public:
    virtual ~Base() { }

    virtual void doSomething()
    {
        /* use member_of_base */
    }
};

class Derived : public Base
{
    double member_of_derived;

public:
    void doSomething() override
    {
        /* use member_of_derived */   
    }
};

The latter would be the true polymorphic approach and normally the way to go; 后者将是真正的多态方法,通常是可行的方法。 whereas the sample above returns void, you might just do all the calculations necessary in base and derived classes until you finally get to some common data type and return this one. 而上面的示例返回的是void,您可能只需要在基类和派生类中进行所有必要的计算,直到最终获得某种通用数据类型并返回该类型。 Example: 例:

class Base
{
    int64_t m_balance; // in 100th of currency in use

public:
    virtual ~Base() { }

    virtual int64_t balance()
    {
        return m_balance;
    }
};

class Derived : public Base
{
    long double m_balance; // arbitrary values in whole currency entities

public:
    int64_t balance() override
    {
        // calculate 100th of currency, correctly rounded:
        return std::llround(m_balance * 100);
    }
};

Admitted, I doubt pretty much representing a balance in double (even if long) is a good idea (issues with rounding, precision, etc)... 诚然,我怀疑以双倍(即使很长)表示平衡是一个好主意(带有四舍五入,精度等问题)...

暂无
暂无

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

相关问题 什么时候是`static_cast <Base*> (的static_cast <void*> (派生))`从指向派生类的指针有效吗? - When is a `static_cast<Base*>(static_cast<void*>(derived))` from a pointer to a derived class valid? 为什么从指向 Base 的指针到指向 Derived 的指针的 static_cast “无效”? - Why is a static_cast from a Pointer to Base to a Pointer to Derived “invalid?” 将派生对象中的“this”指针的static_cast用于基类的问题 - Question of using static_cast on “this” pointer in a derived object to base class C ++如何在不使用static_cast或dynamic_cast的情况下从基类指针访问派生类成员? - C++ How to access derived class member from base class pointer without using a static_cast or dynamic_cast? static_cast从Derived *到void *到Base * - static_cast from Derived* to void* to Base* 使用static_cast初始化可变参数CRTP <Base> (*这个)...:这是合法的吗? - Initializing variadic CRTP with static_cast<Base>(*this)… : is it legal ? 从基类指针到派生类指针的static_cast无效 - static_cast from base class pointer to derived class pointer is invalid static_cast到base析构函数的指向派生类的安全性 - Safety of static_cast to pointer-to-derived class from base destructor 应该static_cast <Derived *> (基本指针)给出编译时错误? - Should static_cast<Derived *>(Base pointer) give compile time error? 使用 static_cast 更改派生结构成员 - using static_cast to change derived struct member
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM