基础类指针使用已分配的内存来派生类指针

Base class pointer to Derived class pointer using the already allocated memory

本文关键字:指针 内存 派生 分配 基础类      更新时间:2023-10-16

参加两个只能由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);

我想做的是将已通过某种方法或函数 convertBase类数据分配/包裹/包装。

更新:为嵌入式系统存储器建造的构建很少,因此我正在尽一切努力减少记忆分配的数量。我只是想知道是否有一种方法可以扩展已经分配的存储器并用衍生物包装。

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

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

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
}

而不是参考,我们可以在必要时使用智能指针。这样,您可以通过构造一个使用A基本对象的数据的新派生对象来避免演员。

在C 中不可能促进类。您可能想做的是 - 就像您说的 - 在Derived中包装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

派生类仅添加方法。

那没有意义。完全。

您可以使用派生到:

  • 覆盖virtual方法(因此自定义行为)=>好
  • 扩展基类的数据=>不良,代码重复使用应使用构图,仍然有效

在您的特殊情况下?这是毫无用处的。它不会将带到表格上。如果您想在基类中添加新功能,则实现免费功能。作为奖励,摆脱了派生的阶级,您还将摆脱铸造的需求。

借助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构造,唯一的开销是在删除旧的Base对象之前创建新的Derived对象。

在完成任何操作之前应该有一张检查,但这将暂时做。

您可以添加一个是基类朋友的助手类,并在其中添加额外的功能,例如。

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
}
Derived *d =static_cast<Derived *>(b); //? :-/

这是一个解释

另一个解释

对引擎盖下发生的事情的更详细说明

更新:

堆栈溢出 - 使用C 中的static_cast降低

使用static_cast

在C 中降低播放

规格:

类型的类型为" b"类型的"指向CV1 B"类型的RVALUE可以是 转换为"指针到CV2 D"类型的RVALUE,其中D是一类 如果从B中得出(第10条),如果从 存在"指向D"到"指向B"的"指针"(4.10),CV2是相同的 cvqualification AS或比CV1更大的CVQualification,并且B不是 D. NULL指针值(4.10)的虚拟基类。转换 到目标类型的空指针值。如果是 类型"指向CV1 B"指向A的B,实际上是 D型的对象,由此产生的指针指向封闭 类型D的对象。否则,演员的结果是未定义的。

仅适用于LLVM:

http://llvm.org/docs/howtosetupllvmstylertti.html-允许降低(不是不确定的行为,因为它不使用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? :-(

编辑

除了所有其他方式,为什么不放置两个对象呢?类型的"基础" 另一种"派生"到联盟的类型?

ps:它的语言规格一致。

浏览我拥有的许多答案,共同的共识是我应该做我所说的事情,并实际上将我的Base类包装在Derived类中。我之所以没有这样做的原因是,我会失去您因继承而获得的特定行为。此行为是将Derived类的指针设置为类型Base的指针,这将在我进行某种转换后会发生,这将使Base类转换为Derived类。

a确实偶然发现了我自己的解决方案 - 尽管显然可能没有编译 - 并且还有许多其他好主意。最后,我意识到,因为对于我的情况,我的Derived类并没有覆盖任何虚拟方法,因此使用继承没有任何好处。最好的方法确实是使用构图。

class Base
{
    // some nice implementation
};
class Derived
{
  public:
    Derived( Base && base )
    {
        this->_base = base;
    }
    Base & base()
    {
        return _base;
    }
  private:
    Base _base;
};