我是C++的新手,我来自Java/C#.
我知道在Java和C#中你可以创建一个类,让另一个类继承它,并覆盖它的功能.然后,您可以创建父类的列表,并将子类的对象插入此列表中.之后,您可以使用被覆盖的功能.
例:
public class Parent
{
public virtual void test()
{
Console.WriteLine("test");
}
}
public class Child : Parent
{
public override void test()
{
Console.WriteLine("test2");
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
List<Parent> tests = new List<Parent>();
tests.Add(new Child());
tests[0].test();
Run Code Online (Sandbox Code Playgroud)
输出:
Run Code Online (Sandbox Code Playgroud)test2
在C++中,当我这样做时std::vector,它调用父的成员函数,而不是子函数.
如何在C++中完成上述操作?
我来自C#和Java的背景,我似乎无法理解C ++中使用指针进行强制转换的含义。
例如:
int x = 1;
char c = *((char*)&x);
Run Code Online (Sandbox Code Playgroud)
它有什么作用?它有什么用?
我正在尝试用C++构建一个可以接受多个客户端的服务器.为此,我构建了一个winsock包装器,并为每个客户端使用带有boost的线程进行通信.
我在尝试接受客户端时遇到了一个奇怪的问题,我有一个看起来像这样的循环.
int clientID = 0;
listenSocket = new Socket(SocketType::TCP);
listenSocket->Bind(port);
listenSocket->Listen();
while(running)
{
Socket *socket = &listenSocket->Accept();
mutex.lock();
clients.push_back(new Client(socket, clientID));
mutex.unlock();
std::cout << "Client with id " << clientID << " connected!" << std::endl;
std::cout << WSAGetLastError() << std::endl;
clientID++;
}
Run Code Online (Sandbox Code Playgroud)
现在,第一个客户端接受罚款并且WSAGetLastError()返回0,但是在第一个连接后,即使我不尝试连接另一个,它只是继续写入控制台10093,这意味着循环中的Accept()停止阻塞由于某种原因不能正确接受.我在网上看到这个错误是由于没有调用WSAStartup()引起的,但是我确实在socket的构造函数中调用了它,并且它在第一次接受了它.
我在我正在处理的项目中使用命名管道,双方都是用 C# 编写的(客户端和服务器),并且都在同一台计算机上(命名管道用于 RPC)。两侧的命名管道设置为使用“PipeTransmissionMode.Message”模式,根据我的理解,该模式应该将传递给 pipe.Write() 的每个数据块“打包”在一条消息中,并将 pipe.Read() 放在另一端应该接收整个消息或不接收任何消息。
在尝试对接收端的数据进行反序列化时,我看到我得到了大量数据,比我发送的数据包还要大。于是我做了一个小测试,我创建了两个Application,server和client,看起来是这样的:
服务器:
class Program
{
static void Main(string[] args)
{
NamedPipeServerStream pipe = new NamedPipeServerStream("TestPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous, 1024, 1024);
pipe.WaitForConnection();
Random random = new Random();
while(true)
{
byte[] buffer = new byte[32];
random.NextBytes(buffer);
pipe.Write(buffer, 0, buffer.Length);
Console.WriteLine(buffer.Length);
}
}
}
Run Code Online (Sandbox Code Playgroud)
客户:
class Program
{
static void Main(string[] args)
{
NamedPipeClientStream pipe = new NamedPipeClientStream(".", "TestPipe", PipeDirection.InOut, PipeOptions.Asynchronous);
pipe.Connect();
while(true)
{
byte[] buffer = new byte[2048];
int read = pipe.Read(buffer, 0, …Run Code Online (Sandbox Code Playgroud) 当我尝试在C中声明堆栈上的数组时,我遇到了一个奇怪的问题.我一直认为(至少到现在为止)如果没有常量表达式就不可能在堆栈上声明数组.例如,尝试在Windows上的VS2015上编译以下代码:
int main()
{
int i = 3;
int test[i];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
产生"表达式必须具有常量值"错误,这是我所期望的,但是在Linux机器上使用gcc和clang编译相同的代码是有效的.起初我以为这可能是编译器推断的东西,所以我尝试了以下内容:
int main()
{
int i = 3;
int j = i*i;
int test[j];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
VS2015再次抱怨同样的错误,但是gcc和clang编译得很好!我立即想,好吧也许这些编译器也在推断它,毕竟它只是"不变"的表达式.所以我尝试了以下方法:
int main()
{
int i = getchar();
int test[i];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当然编译器无法推断这一点,i用于声明的test值只能在运行时知道,但令我惊讶的是,VS2015再次抱怨,但是gcc和clang编译了它......甚至添加了以下内容:
int main()
{
int i = getchar();
int test[i];
printf("%d\n", sizeof(test) / sizeof(int));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
并x在ASCII表中输入其值为120的字符,输出120.
这是怎么回事?
我正在尝试为某些win32 api函数编写一个trampoline挂钩,当我将JMP指令写入原始函数的开头时,我希望它跳转到codecave而不是调用函数.
OllyDBG中的原始函数start如下所示:
PUSH 14
MOV EAX, 12345678
...
Run Code Online (Sandbox Code Playgroud)
我将其修补为:
JMP 87654321
NOP
NOP
Run Code Online (Sandbox Code Playgroud)
以下功能的地址:
int HookFunc(int param)
{
DoStuff(param);
return ExecuteOriginal(param);
}
Run Code Online (Sandbox Code Playgroud)
ExceuteOriginal看起来像这样:
unsigned long address = AddressOfOriginalFunction + 7;
int ExceuteOriginal(int param)
{
__asm
{
PUSH 0x14
MOV EAX, 0x12345678
JMP address
}
}
Run Code Online (Sandbox Code Playgroud)
执行被覆盖的代码并在修补后的代码后立即跳转到原始函数.问题在于,由于它是一个函数,它会使堆栈陷入困境,因为调用者应该清理它并且函数而不是返回,跳转到另一个函数的代码.我猜这就是程序崩溃的原因.
有没有办法使用Visual C++编译器将汇编代码放在程序的代码部分而不是在函数内部?这样我就可以跳到那里,执行任何操作,然后返回,而不会有弄乱堆栈的风险.
Roslyn是一个完整的独立C#编译器吗?我看了一下源代码,似乎它使用了Visual Studio中的编译器,我也没有在它的GitHub存储库(https://github.com/dotnet/roslyn)中找到任何源代码与解析有关.