[英]Why can I print out a privately inherited member of the Base class through a publicly inhterited method of the SubBase class?
[英]Print out memory content for base and inherited class
我試圖添加一個print()成員函數,該函數將輸出對象的內存內容,如下所示:
#include <iostream>
#include <string>
class A {
public:
virtual std::string print() {
std::string s;
s.append(reinterpret_cast<char*>(this), 0, sizeof(A));
return s;
}
};
class B : public A {
public:
B() : a('a') {}
char a;
};
int main() {
A a;
B b;
std::cout << "A \"" << a.print() << "\"\n";
std::cout << "B \"" << b.print() << "\"\n";
return 0;
}
如何打印B的整個長度,上面的清單僅打印B類的A部分。
為了安全地執行此操作,您必須覆蓋B的虛函數:
std::string print() override {
std::string s;
s.append(reinterpret_cast<char*>(this), 0, sizeof(B));
return s;
}
為什么呢 因為您不能確定A和B具有相同的地址(例如,如果有多個基類 )。
如果您喜歡這種轉儲功能,為了減少代碼,可以使用模板並在每個替代中調用該模板。
使用具有非虛擬功能的模板庫。
template<class T> class PrintMe
{
public:
std::string print() const
{
std::string s;
s.append(reinterpret_cast<char*>(this), 0, sizeof(T));
return s;
};
};
class A: public PrintMe<A>
{
// whatever
};
class B: public PrintMe<B>
{
};
// and in code which uses it
std::cout << some_b.print();
本質上,規則是任何需要打印自身能力的類X
從PrintMe<X>
繼承。
就我個人而言,我不會使用繼承或將其用作類的成員函數,而是
template<class T> std::string print(const T &x)
{
std::string s;
s.append(reinterpret_cast<char*>(&x), 0, sizeof(x));
return s;
}
// and in some code which needs this
std::cout << print(some_b);
// or, more explicitly
std::cout << print<B>(some_b);
請注意,這完全避免了虛擬函數的分派,而是依賴於在編譯時識別的對象的類型。
如何打印B的整個長度...
您可能會考慮在類層次結構中“鏈接”您的打印方法。
您的計划無法處理不可打印的值。 我也看不到“十六進制”轉換。 但是,假設您將演員表轉換為char *就可以了...
class A {
public:
virtual std::string print() {
std::string s;
s.append(reinterpret_cast<char*>(this), 0, sizeof(A));
return s;
}
};
class B : public A {
public:
B() : a('a') {}
char a;
virtual std::string print() {
std::string s = A::print(); // get A contents
s.append(reinterpret_cast<char*>(this), 0, sizeof(B));
return s;
}
};
未經測試。
同樣,這些問題取決於實現。
根據我的經驗(幾乎完全使用g ++),B的實例包含A和B的所有數據(我認為A在最前面,即低位地址)。 A的實例只有A的數據,無法分辨,也不知道任何派生類。
如果在您的實現中,B擁有A和B的所有數據(易於說明,只需打印sizeof(A)和sizeof(B)並與期望值進行比較。),則無需在B內部調用A :: print() ::打印()。
還要注意-如果任何一個類都使用容器,則您希望打印的容器數據可能不在類實例的堆棧空間中。 容器(向量,堆,列表等)使用堆。 因此,您將在堆棧上找到指針,並在其他位置找到數據。
更新-
這只是一個小嘗試,以揭示g ++實現細節的一部分。
我的解釋是,它表明B類實例在B類數據屬性的前面(較低地址)包含A類實例的數據屬性。 B是A的兩倍。
對於此代碼,我刪除了虛擬關鍵字。 虛擬以我期望的方式影響這些對象的大小。 但是沒有關鍵字,大小恰好是我對uint64_t .. 8(在A中)和16(在B中)字節的期望。
class A
{
public:
A() :
aData(0x3132333435363738)
{
}
~A(){ }
std::string dump()
{
std::stringstream ss;
ss << " this: " << &(*this);
ss << " aData: " << &aData << std::endl;
return(ss.str());
}
std::string show()
{
std::stringstream ss;
ss << std::hex << "0X" << aData << std::endl;
return ss.str();
}
uint64_t aData; // 8 bytes
};
class B : public A
{
public:
B() : bData(0x3837363534333231)
{
}
~B(){ }
uint64_t bData; // 8 bytes
std::string dump()
{
std::stringstream ss;
ss << " this: " << &(*this);
ss << " A::aData: " << &(A::aData) << " bData:" << &bData
<< std::endl;
return(ss.str());
}
std::string show()
{
std::stringstream ss;
ss << std::hex << "0x" << A::aData << " 0x" << bData
<< std::endl;
return ss.str();
}
};
int t405(void)
{
A a;
B b;
std::cout << "\nsizeof(a): " << sizeof(a) << std::endl;
std::cout << "sizeof(b): " << sizeof(b) << std::endl;
std::cout << "\ninstance a: " << &a << std::endl;
std::cout << "instance b: " << &b << std::endl;
std::cout << "\ninstance a - aData: " << a.dump() << std::flush;
std::cout << "\ninstance b - bData: " << b.dump() << std::flush;
std::cout << "\ninstance a show(): " << a.show() << std::flush;
std::cout << "\ninstance b show(): " << b.show() << std::flush;
return(0);
}
輸出應如下所示:
sizeof(a): 8 sizeof(b): 16
instance a: 0x7ffe73f5b5d0 instance b: 0x7ffe73f5b5e0
instance a - aData: this: 0x7ffe73f5b5d0 aData: 0x7ffe73f5b5d0
instance b - bData: this: 0x7ffe73f5b5e0 A::aData: 0x7ffe73f5b5e0 bData:0x7ffe73f5b5e8
instance a show(): 0X3132333435363738
instance b show(): 0x3132333435363738 0x3837363534333231
首先,您可以#include <stdint.h>
現在您可以將對象轉換為uint8_t,並通過for循環對其進行迭代(大小= sizeof(object))。
通過printf將其十六進制值打印到stdin:
printf("%hu", val[i]);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.