[英]Accessing class members that are arrays through “pointers to class members”
[英]Why does statically accessing class data members via pointers returns 1?
給出以下代碼:
#include <iostream>
using std::cout;
class A {
public:
virtual ~A() {}
int x,y,z;
};
int main (void)
{
std::cout<<&A::x;
std::cout<<&A::y;
std::cout<<&A::z;
}
輸出是:
111
輸出是什么意思? 為什么是1? 是否有任何理由通過指針訪問類成員(沒有創建對象)?
編輯 - 使用:
printf("%p",&A::x);
printf("%p",&A::y);
printf("%p",&A::z);
打印:4,8和C.
現在我覺得更有意義..(字節)但是,還有什么用呢?
沒有為T = &C::m
定義的operator<<(std::ostream&, T)
。 通常你會收到一個錯誤。
但相反,有一個用於T = bool
和從成員指針到bool
的隱式轉換。 所以你看到的輸出只是那些指針不為空(被轉換為true
)的結果。
試試這個,例如:
#include <iomanip>
#include <iostream>
struct A
{
int x, y, z;
};
int main()
{
std::cout << std::boolalpha; // print boolean values as text
std::cout << &A::x << std::endl;
std::cout << &A::y << std::endl;
std::cout << &A::z << std::endl;
}
輸出:
真正
真正
真正
請注意,在代碼printf("%p", &A::X)
,您有未定義的行為。
%p
說明符的值必須是void*
,並且不存在從成員指針到void*
。 相反,你有什么別名(類型雙關語)到void*
,這是未定義的行為。 (想象一下, sizeof(&A::x)
是4而sizeof(void*)
是64;沒有人說這不是這種情況。)
你只需要接受這樣的想法:並非所有指針都可以被視為整數偏移。 我們甚至可以打印一個指針是實現定義的:它可以打印“apple”為null,“pear”為一個值,“milk”為另一個(如果(啞)實現想要)。 我之前已經觸及過價值觀和表現形式之間的差異 。
在這種情況下,沒有輸出的價值可言 。 這沒關系,並非所有值都有有意義的打印輸出。 你能做的最多就是打印出各個位:
#include <climits>
#include <iostream>
#include <type_traits>
template <typename T>
auto print_bits(const T& value)
-> typename std::enable_if<std::is_standard_layout<T>::value>::type
{
// it's okay to alias a standard-layout type as a sequence of bytes:
const auto valueAsBytes = reinterpret_cast<const unsigned char*>(&value);
for (std::size_t byte = 0; byte < sizeof(T); ++byte)
{
// print in reverse order
const std::size_t byteIndex = sizeof(T) - byte - 1;
const unsigned char byteValue = valueAsBytes[byteIndex];
for (std::size_t bit = 0; bit < CHAR_BIT; ++bit)
{
// print in reverse order
const std::size_t bitIndex = CHAR_BIT - bit - 1;
const bool bitValue = (byteValue & (1U << bitIndex)) != 0;
std::cout << (bitValue ? 1 : 0);
}
std::cout << ' ';
}
std::cout << std::endl;
}
(我以相反的順序打印字節和位,因為在我的體系結構中,這會將最低有效位放在右邊。我更喜歡以這種方式查看二進制值。)
這給出了:
struct A
{
int x, y, z;
};
int main()
{
// example:
for (unsigned i = 0; i < 64; ++i)
print_bits(i);
std::cout << std::endl;
// member-pointers:
print_bits(&A::x);
print_bits(&A::y);
print_bits(&A::z);
}
輸出:
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000010
[...]
00000000 00000000 00000000 00111101
00000000 00000000 00000000 00111110
00000000 00000000 00000000 0011111100000000 00000000 00000000 00000000
00000000 00000000 00000000 00000100
00000000 00000000 00000000 00001000
您對成員指針的看法無法保證。
&A::x
創建指向 A
類成員的指針 。 在某種程度上,指向成員的指針表示該成員在該類中的“位置”。 這些數字究竟意味着什么取決於具體實施。 我猜想在你的特定實現中,它意味着 編輯實際上,GManNickG的答案表明我對這個假設是錯誤的,它只是將指針打印成隱式轉換為x
在類中的索引1上(虛函數表指針在索引0上)。bool
成員。
請注意, 指向成員的指針不是傳統意義上的指針。 您不能直接取消引用指向成員的指針。 你總是需要一個對象的指針/引用來跟隨它。 示例(使用您的班級):
int main()
{
int A::*pm; // pm is a pointer to member of A of type int
A a;
pm = &A::x;
std::cout << a.*pm; //will output a.x
pm = &A::y;
std::cout << a.*pm; //will output a.y
A *pa = &a;
std::cout << pa->*pm; //will output pa->y
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.