记录内存地址
如果你想使用 iostreams 输出指针(例如用于日志记录),那么通过void*
是确保的唯一方法operator<<
并没有以某种疯狂的方式超载。
#include <iostream>
struct foo {
};
std::ostream& operator<<(std::ostream& out, foo*) {
return out<<"it's a trap!";
}
int main() {
foo bar;
foo *ptr = &bar;
std::cout << ptr << std::endl;
std::cout << static_cast<void*>(ptr) << std::endl;
}
测试 iostream 状态
iostreams 过载operator void*
作为状态检查,语法如下if (stream)
or while (stream)
是测试流状态的简写方法。
模板元编程
您可能想使用void*
使用模板元编程有时可以减少包罗万象,例如使用 SFINAE 技巧,但通常有一种更好的方法,使用一种或另一种形式的部分特化。
访问最派生指针
正如阿尔夫在评论中指出的那样dynamic_cast<void*>
对于获取层次结构中最派生的类型也很有用,例如:
#include <iostream>
struct other {
virtual void func() = 0;
int c;
};
struct foo {
virtual void func() { std::cout << "foo" << std::endl; }
int a;
};
struct bar : foo, other {
virtual void func() { std::cout << "bar" << std::endl; }
int b;
};
namespace {
void f(foo *ptr) {
ptr->func();
std::cout << ptr << std::endl;
std::cout << dynamic_cast<void*>(ptr) << std::endl;
}
void g(other *ptr) {
ptr->func();
std::cout << ptr << std::endl;
std::cout << dynamic_cast<void*>(ptr) << std::endl;
}
}
int main() {
foo a;
bar b;
f(&a);
f(&b);
g(&b);
}
Gives:
foo
0xbfb815f8
0xbfb815f8
bar
0xbfb815e4
0xbfb815e4
bar
0xbfb815ec
0xbfb815e4
在我的系统上。
例外情况
§ 15.3.1 规定:
异常声明不应表示指针或引用
除 void* 之外的不完整类型,const void*
,挥发性无效*,或
常量易失性无效*。
因此,捕获指向不完整类型的指针的唯一合法方法似乎是通过void*
。 (虽然我认为如果你真的需要使用它可能会有更大的问题)
旧版 C 的用途
有很多“遗留”C 用途void*
用于在不知道数据是什么的情况下存储指向数据的指针,但在新的 C++ 代码中几乎总是有更好的方法来表达相同的功能。