c++ managed class constructor can not have parameters? - managed-c++

please help me out , why my code cannot compile,
the compiler complains that:
error C2629: 意外的“StringToAnsi (”
error C2334: “{”的前面有意外标记;跳过明显的函数体
error C2629: 意外的“StringToAnsi (”
...
Here is my code:
#using <System.dll>
#using <mscorlib.dll>
class StringToAnsi
{
private:
void * m_ptr;
public:
StringToAnsi( System::Object ^ str)
{
m_ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(safe_cast<System::String^>(str)).ToPointer();
}
StringToAnsi(System::String ^ str)
{
m_ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(str).ToPointer();
}
~StringToAnsi()
{
System::Runtime::InteropServices::Marshal::FreeHGlobal(System::IntPtr(m_ptr));
}
operator const ACHAR*()
{
return (const ACHAR*)m_ptr;
}

Because you have two constructors with the same number of parameters. There is an Object and a String, but both are an Object. So this seems very ambiguous.
When you create two methods (or constructors), you can't let them have the same number of parameters, because the compiler doesn't know which one to call.
When you put in a string into the construction like so: new StringToAnsi("bla"). The compiler doesn't know which constructor to use.

Related

What is the alternative to std::atexit in C++

I wanted to remove file when the program is closed, but not ended. I tried to do it with function std::atexit, but its parameter can't be pointer to a function if that's class member function. So I was wondering is there any simple alternative?
class User
{
std::experimental::filesystem::path file_path;
std::experimental::filesystem::path & get_file_path();
void clean_file_path();
void (User::*x)();
}
int main()
{
std::experimental::filesystem::path p = user.get_file_path();
user.x = & User::clean_file_path;
std::ofstream output(p, std::ios::binary | std::ios::trunc);
std::atexit(user.x);
}
You could have a static function inside your class and you could call "atexit" with a pointer to this static function:
class User
{
public:
void clean();
static void cleanStatic();
};
int main()
{
void (User:: * pClean)() = &User::clean;
void (*pCleanStatic)() = &User::cleanStatic;
std::atexit(pCleanStatic);
}
You can register multiple functions with "atexit" but there is a limit to that number so maybe registering only one function that will handle the work for all the objects is a better solution.
One more thing: the type of pCleanStatic and the type of pClean are not the same:
pCleanStatic is void(*)()
pClean is void(User::*)()
"atexit" expects a parameter of type void(*)(). So only pCleanStatic will be accepted as a parameter. In Visual Studio, if you try to compile the code
std::atexit(pClean);
you'll get the following error:
error C2664: 'int atexit(void (__cdecl *)(void))': cannot convert argument 1 from 'void (__thiscall User::* )(void)' to 'void (__cdecl *)(void)'
mentioning the two different types.

Pass a typed function as a parameter in Dart

I know the Function class can be passed as a parameter to another function, like this:
void doSomething(Function f) {
f(123);
}
But is there a way to constrain the arguments and the return type of the function parameter?
For instance, in this case f is being invoked directly on an integer, but what if it was a function accepting a different type?
I tried passing it as a Function<Integer>, but Function is not a parametric type.
Is there any other way to specify the signature of the function being passed as a parameter?
Dart v1.23 added a new syntax for writing function types which also works in-line.
void doSomething(Function(int) f) {
f(123);
}
It has the advantage over the function-parameter syntax that you can also use it for variables or anywhere else you want to write a type.
void doSomething(Function(int) f) {
Function(int) g = f;
g(123);
}
var x = <int Function(int)>[];
int Function(int) returnsAFunction() => (int x) => x + 1;
int Function(int) Function() functionValue = returnsAFunction;
To strongly type a function in dart do the following:
Write down the Function keyword
Function
Prefix it with its return type (for example void)
void Function
Append it with parentheses
void Function()
Put comma separated arguments inside the parentheses
void Function(int, int)
Optionally - give names to your arguments
void Function(int foo, int bar)
Real life example:
void doSomething(void Function(int arg) f) {
f(123);
}
Edit: Note that this answer contains outdated information. See Irn's answer for more up-to-date information.
Just to expand on Randal's answer, your code might look something like:
typedef void IntegerArgument(int x);
void doSomething(IntegerArgument f) {
f(123);
}
Function<int> seems like it would be a nice idea but the problem is that we might want to specify return type as well as the type of an arbitrary number of arguments.
For reference.
int execute(int func(int a, int b)) => func(4, 3);
print(execute((a, b) => a + b));
You can have a function typed parameter or use a typedef
void main() {
doSomething(xToString);
doSomething2(xToString);
}
String xToString(int s) => 's';
typedef String XToStringFn(int s);
void doSomething(String f(int s)) {
print('value: ${f(123)}');
}
void doSomething2(XToStringFn f) {
print('value: ${f(123)}');
}
DartPad example
This is what typedefs are for!

vector base derived class

I am not able to call negedge of all the subscribers who register for clock, all subscribers also derive from ClkIf
class ClkAdapter : public ClkIf
{
virtual void negedge()
{
for(std::list<ClkIf*>::iterator it = clk_list.begin(); it != clk_list.end(); it++)
(it->negedge)();
}
virtual void posedge()
{ clk_cnt++; }
void registerForClock(ClkIf* module)
{ clk_list.push_back(module); }
std::list<ClkIf*> clk_list;
unsigned long long clk_cnt;
};
error: request for member 'negedge' in '* it.std::_List_iterator<_Tp>::operator-> with _Tp = ClkIf*', which is of non-class type 'ClkIf*'
Error in negedge function, What is wrong in this code??
You have a list of pointers, so the list iterator would work similarly to a double pointer (that is, ClkIf**). Thus, you would have to call (*it)->negedge() within the loop. The (*it) fetchs the current ClkIf* element first, and then the -> operator calls the function on that value.

How to change the variable name by reflection?

I have a variable like this:
People model=Mock()//created by spock' mock
How to change the variable name "model" to "model_0" by reflection?
I doubt there is any way to do that with reflection. I'm with #tim_yates in this one.
I'm no bytecode/compiler expert, but i do believe variable's names turn into symbols upon compilation, so they are not changeable at all. The following Java class:
public class Var {
void a() {
int myVar = 1;
myVar += 1;
}
}
Upon compilation and decompilation (using jd-gui), the code turns into:
public class Var
{
void a()
{
int i = 1;
i++;
}
}
The variable name changed.
On Groovy, you can go for ASTs, which will give you full power over the generated tree. The following class:
class Asts {
def wat() {
Integer myVar = 90
}
}
Will generate the following AST:
Now you can write your own AST transformation to make the changes. Doesn't seem worth to me, though, a collection or map should suffice.

Managed class does not compile

I have the following code in Visual C++:
#using <mscorlib.dll>
using namespace System;
__gc class classEx
{
public:
classEx()
{
data = "abcd";
}
classEx(String *s)
{
data=s;
}
String* getNombre()
{
return data;
}
void setNombre(String *s)
{
data=s;
}
private:
String* data;
};
int main(void)
{
classEx* obj = new classEx();
return 0;
}
I have changed the Configuration Manager to Release and Build is checked. The problem is when I try to compile it appears a bunch of errors, such as:
error C4980: '__gc' : use of this keyword requires /clr:oldSyntax command line option
cannot use this indirection on type 'System::String'
The last error points that I cannot use in the second constructor the String *s. Why is that?
Is there something that I am missing?
If you will set a corresponding compiler option to clr:oldsyntax in the project properties as the first message says, then the following code compiles without errors in Visual Studio 2010:
#include "stdafx.h"
using namespace System;
__gc class A
{
public:
A( String *s ) : data( s ) {}
String * get_data() { return data; }
private:
String *data;
};
int main()
{
A *pa = new A( "Hello World" );
Console::WriteLine( pa->get_data() );
return 0;
}
It seems that the second message is the result of that you did not set the option pointed out in the first message.
You should select menu Project → Properties → General → *Supporting of CLR (or something else because I have the Russian release of Visual Studio 2010 I can not name the option exactly in English) → clr:oldsyntax
You need to use different syntax for managed code (not the * operator):
String ^ data;
You'll also need the /clr command line option.
This article has a wealth of examples:
String (C++/CLI and C++/CX)

Resources