C++ 基类指针指向使用已分配内存的派生类指针

C++ 基类指针指向使用已分配内存的派生类指针,c++,c++11,C++,C++11,选取两个只能由new创建的类。一类是基类,另一类是派生类。派生类只添加方法 class Base {}; class Derived : public Base {}; Base * b = new Base{} Derived * d = covert( b ); // - or - Base * b = new Base{}; convert( b ); // converts Base to Derived Derived * d = dynamic_cast<Derived

选取两个只能由
new
创建的类。一类是基类,另一类是派生类。派生类只添加方法

class Base
{};

class Derived : public Base
{};

Base * b = new Base{}
Derived * d = covert( b );

// - or -

Base * b = new Base{};
convert( b ); // converts Base to Derived
Derived * d = dynamic_cast<Derived *>(b);
类基
{};
派生类:公共基
{};
Base*b=新的Base{}
派生*d=隐蔽(b);
//-或-
Base*b=新的Base{};
转换(b);//将基转换为派生
导出*d=动态_投射(b);
我要做的是获取已分配的
Base
类数据,并通过某种方法或函数
convert
使用导数进行扩展/换行

更新: 为嵌入式系统构建内存是稀缺的,所以我正在尽我所能减少内存分配量。我只是想知道是否有一种方法可以扩展已经分配了内存的基类,并用派生函数包装它

更多更新:
虽然嵌入式系统是ARM,我目前正在使用LLVM编译器,但将来可能不会这样。因此,首选符合标准的方法。

您可以添加一个助手类,它是基类的朋友,并向该类添加额外的函数,例如

class Base 
{
   friend class BaseHelper;
   // ....
};
class BaseHelper
{
    public:
    // all functions can access data into Base objects:
    void f(const Base& b) const; // can only read data in b, not change it
    void g(Base& b); // can change data in b
}

您可以添加一个助手类,它是基类的朋友,并向其添加额外的函数,例如

class Base 
{
   friend class BaseHelper;
   // ....
};
class BaseHelper
{
    public:
    // all functions can access data into Base objects:
    void f(const Base& b) const; // can only read data in b, not change it
    void g(Base& b); // can change data in b
}

<>在C++中不可能使用类。您可能想做的是—就像您所说的—将
Base
包装到
派生的

class BaseInterface { ... };

class DerivedInterface: public BaseInterface { ... };

class Base: public BaseInterface { ... };

class Derived: public DerivedInterface {
private:
  Base* base;
public:
  Derived(Base* useBase): base(useBase) {}
  ~Derived() { delete base; }
  // implement using base
};
然后像这样使用它:

Base* object = new Base(...);
// use object with base functionality
object = new Derived(object);
// use object with derived functionality
delete object; // free both base and derived memory

<>在C++中不可能使用类。您可能想做的是—就像您所说的—将
Base
包装到
派生的

class BaseInterface { ... };

class DerivedInterface: public BaseInterface { ... };

class Base: public BaseInterface { ... };

class Derived: public DerivedInterface {
private:
  Base* base;
public:
  Derived(Base* useBase): base(useBase) {}
  ~Derived() { delete base; }
  // implement using base
};
然后像这样使用它:

Base* object = new Base(...);
// use object with base functionality
object = new Derived(object);
// use object with derived functionality
delete object; // free both base and derived memory

如果我正确理解您的问题,一个可能的解决方案是使用聚合而不是继承

class Base
{/*has only the data*/}

class Derived 
{
    Base &base;
    Derived(Base &b) : base(b) {}
    //now methods from derived will use the data members from instance passed in constructor
    //if is possible the Derived needs to be a friend class of Base in case there are no getter for all members
}
如果需要,我们可以使用智能指针来代替引用。
通过这种方式,您可以通过构造一个新的派生对象来避免强制转换,该对象使用来自基本对象的数据。

如果我正确理解您的问题,一个可能的解决方案是使用聚合而不是继承

class Base
{/*has only the data*/}

class Derived 
{
    Base &base;
    Derived(Base &b) : base(b) {}
    //now methods from derived will use the data members from instance passed in constructor
    //if is possible the Derived needs to be a friend class of Base in case there are no getter for all members
}
Derived *d =static_cast<Derived *>(b); //? :-/
如果需要,我们可以使用智能指针来代替引用。 通过这种方式,您可以通过构造一个新的派生对象来避免强制转换,该派生对象使用来自基本对象的数据。

Derived*d=static_cast(b);/?:-/
Derived *d =static_cast<Derived *>(b); //? :-/

更新:

规格:

类型为“指向cv1 B的指针”的右值,其中B是类类型,可以 转换为“指向cv2 D的指针”类型的右值,其中D是一个类 从B派生(第10条),如果从 存在“指向D的指针”到“指向B的指针”(4.10),cv2相同 CVA鉴定为或大于cv1的CVA鉴定,且B不是 D的虚拟基类。转换空指针值(4.10) 指向目标类型的空指针值。如果 类型“指向cv1 B的指针”指向实际上是的子对象的B 类型为D的对象,结果指针指向封闭的 类型为D的对象。否则,强制转换的结果未定义

仅限LLVM:

允许向下转换(不是未定义的行为,因为它不使用C++ RTTI)。 没有符合标准的向下投射方式:

class Parent{
    public: void gotoWork(){ cout << doWork(); }
};

class Child: public Parent{
     public: void gotoSchool(){ cout << attendClasses();}
};

Parent *p = new Parent();
Child *ch = static_cast<Child*> p;
//now child has to go work? :-(
类父类{
public:void gotoWork(){cout
Derived*d=static_cast(b);/?:-/

更新:

规格:

类型为“指向cv1 B的指针”的右值,其中B是类类型,可以 转换为“指向cv2 D的指针”类型的右值,其中D是一个类 从B派生(第10条),如果从 存在“指向D的指针”到“指向B的指针”(4.10),cv2相同 CVA鉴定为或大于cv1的CVA鉴定,且B不是 D的虚拟基类。转换空指针值(4.10) 指向目标类型的空指针值。如果 类型“指向cv1 B的指针”指向实际上是的子对象的B 类型为D的对象,结果指针指向封闭的 类型为D的对象。否则,强制转换的结果未定义

仅限LLVM:

允许向下转换(不是未定义的行为,因为它不使用C++ RTTI)。 没有符合标准的向下投射方式:

class Parent{
    public: void gotoWork(){ cout << doWork(); }
};

class Child: public Parent{
     public: void gotoSchool(){ cout << attendClasses();}
};

Parent *p = new Parent();
Child *ch = static_cast<Child*> p;
//now child has to go work? :-(
类父类{
public:void gotoWork(){cout
派生类只添加方法

class Base
{};

class Derived : public Base
{};

Base * b = new Base{}
Derived * d = covert( b );

// - or -

Base * b = new Base{};
convert( b ); // converts Base to Derived
Derived * d = dynamic_cast<Derived *>(b);
那么这门课就毫无意义了

您可以使用派生来:

  • 覆盖
    virtual
    方法(从而定制行为)=>良好
  • 扩展基类的数据=>Bad,代码重用应该使用组合,但仍然有效
在你的特殊情况下?它只是无用的。它不会带来任何东西。如果你想给基类添加新功能,那么就实现自由函数。作为奖励,摆脱派生类,你也将摆脱强制转换的需要

派生类只添加方法

class Base
{};

class Derived : public Base
{};

Base * b = new Base{}
Derived * d = covert( b );

// - or -

Base * b = new Base{};
convert( b ); // converts Base to Derived
Derived * d = dynamic_cast<Derived *>(b);
那么这门课就毫无意义了

您可以使用派生来:

  • 覆盖
    virtual
    方法(从而定制行为)=>良好
  • 扩展基类的数据=>Bad,代码重用应该使用组合,但仍然有效

在你的特殊情况下?它只是无用的。它不会带来任何东西。如果你想给基类添加新功能,那么就实现自由函数。作为奖励,摆脱派生类,你也将摆脱强制转换的需要。

多亏了C++11,一个潜在的选择出现了

class Base
{
  pubilc:
    Data data;

    Base( Base && base ) : data( std::move( base.data ) ) {} 
};

class Derived : public Base
{
  pubilc:
    static Derived * convert( Base *& base )
    {
        Derived * d = new Derived{ std::move( *base ) };
        delete base;

        base = d;
        return d;
    }
 };
虽然这不是我所希望的记忆方式,但据我所知,这只是一个小小的成功。通过使用move构造,唯一的开销是在删除旧的
基对象之前创建一个新的
派生的
对象

在做任何事情之前都应该检查一下,但是这个