繁体   English   中英

C ++中的void指针

[英]void pointers in C++

我在一个网站上看到了这个例子,网站提到: - “它的一个用途(void指针)可能是将通用参数传递给一个函数”

// increaser
#include <iostream>
using namespace std;

void increase (void* data, int psize)
{
  if ( psize == sizeof(char) )
  { char* pchar; pchar=(char*)data; ++(*pchar); }
  else if (psize == sizeof(int) )
  { int* pint; pint=(int*)data; ++(*pint); }
}

int main ()
{
  char a = 'x';
  int b = 1602;
  increase (&a,sizeof(a));
  increase (&b,sizeof(b));
  cout << a << ", " << b << endl;
  return 0;
}

编写如下代码会不会更简单?

void increaseChar (char* charData)
{
    ++(*charData);
}

void increaseInt (int* intData)
{
    ++(*intData);
}

int main ()
{
  char a = 'x';
  int b = 1602;
  increaseChar (&a);
  increaseInt (&b);
  cout << a << ", " << b << endl;
  string str;
  cin >> str;
  return 0;
}

代码更少,而且非常简单。 在第一个代码中,我不得不在这里发送数据类型的大小!

最好使函数类型安全且通用。 最好通过引用而不是指针来获取参数:

template <typename T>
void increment(T& data) {
    ++data;
}

在C ++中应尽可能避免使用void* ,因为模板和继承提供了类型安全的替代方法。

你的代码绝对是可取的。 void*失去任何类型安全的假装,你的类型安全过载要好得多。 良好的直觉。

要在C ++中一般支持更多类型,您可以定义类或函数模板,而不是使用void* 引用优于指针,但您的代码可以更改为:

template <class T> T increase(T* value)
{
    return ++(*value);
}

int main(int argc, char* argv[])
{
    int i(0);
    increase<int>(&i);

    char c(0);
    increase<char>(&c);

    return 0;
}

作为一个有趣的问题,该网站是什么?

您的解决方案仅适用于int或char。 考虑一下你想要通过一些自定义类型(例如struct)的数组的情况。 在您的代码中,您需要添加一个方法来执行此操作,但是在上面的示例中,不应添加任何行来获取工作示例。

“它的一个用途(void指针)可能是将泛型参数传递给函数”

肯定不是一种好的用途。 将通用参数传递给函数的方法是:

a)允许编写安全代码的模板(以及可能的模板特化),
b) OOP方法。

我喜欢你的第二次increaseIntincreaseChar更好的解决方案。 您可以将其重写为:

template<typename T>
void increase(T* pData)
{
    ++(*pData);
}

它适用于任何支持++并且安全的类型。


有时你仍然需要一个void指针作为“通用参数” - 例如在使用流行的pthread库时。 当你产生一个线程时,你可以发送一些任意数据(你想要的任何类型),并且使用 - well - 一个void*指针完成它。 pthread库是C而不是C ++,这可能是原因之一,但您可能希望从C ++接口,这确实需要您将void*指针用作“泛型类型”。 但是,那里没有太大的伤害; 请记住,对于日常编码,有更优雅的解决方案。

其实我觉得这个例子很糟糕。 其中一个规范示例是C库的qsort ,您可以在其中传递void* 以及解释数据的函数。

但是,在C ++中,有更好的机制可用于静默故障。

因此,使用void*传递通用数据可能应该限于

  1. 代码膨胀很重要的实例
  2. 与其他语言交互的代码,特别是C.

当你编程C(而不是C ++)时,void *只是你做一些通用的方法。 然而这个例子很可怕。 此方案通常用于回调机制,您可以在其中传递函数指针和void *。 例如:

void handle_crash(void* data)
{
    Log* log = (Log*)data;
    log->print("We crashed.");
}

Log log;
set_crash_handler(&handle_crash, &log);

您将经常在C框架上看到这一点,例如libxml2或spidermonkey。 在C的情况下,这是唯一可以实现它的东西。 它不是一个非常强大的解决方案。

如果您使用的是C ++,则可以选择更多选项。 基本通用编程可以使用模板或重载完成,如其他答案中所述。 如果您需要可靠的回调机制,您可能需要查看libsigc ++或其他“信号和插槽”框架。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM