• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1312
  • Last Modified:

C++/CLI default constructor for struct -- error C3417

I understand from http://msdn.microsoft.com/en-us/library/ekfb4tkd(VS.80).aspx that the default constructor in the code below is what's tripping the error.

But I need that default constructor ... or something equivalent.  What can I do?

Thanks!
value struct PointFloat {
public:
	PointFloat() {
		X = Y = 0.0f;
	}
	PointFloat(float _X, float _Y) {
		X = _X; Y = _Y;
	}
	float X;
	float Y;
};

Open in new window

0
Daniel Wilson
Asked:
Daniel Wilson
  • 5
  • 4
  • 3
  • +1
3 Solutions
 
mrjoltcolaCommented:
C# does not allow default constructor for structs. Change it to a class if you need that, or use the 2nd constructor (float, float)
0
 
mrjoltcolaCommented:
Eep, this is C++, I read my 2nd question wrong today! :(

But the answer is the same,  because you are mapping the C++ struct to a .NET value type. It is not just C#, it is the .NET CLR that does not allow default no-arg constructors, because the CLR already defines that.

So, why not just use the 2-arg constructor?

Are you compiling in CLI mode on purpose? If you don't need managed C++, then you can just use standard C++ and the above is legal. Its a CLI issue only.

0
 
tcullerCommented:
When you declare something as a "value struct" in Managed C++, this becomes a "managed" struct. Managed Structs and managed classes are nearly identical except for a few major differences:
 - Managed structs are passed by VALUE (i.e, every time you pass one, it "copies" itself)
 - Managed structs do NOT support any form of inheritance, though you can implement interfaces.
 - Though managed structs are copied, the copy is a "shallow" copy, so having any references to classes within one will still point to the same object.

Every time you make a managed struct, it actually generates a default constructor for you. Unfortunately, there is no way around this--any attempt will just cause a compilation error.

By the way, you are aware that there is already a float version of a 2-D point in the System.Drawing namespace (within the System.Drawing.dll assembly) called System.Drawing.PointF, correct? Plus, the floats within that type are fixed, using System.Single instead of C++'s screwy primitive data types.

When a managed struct is created, ALL fields within that struct are immediately initialized to their defualt values--in this case, your default constructor is no different than the one generated by the compiler. They will both assign 0.0F to both X and Y.

Hope that helps,
Nate
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
tcullerCommented:
Whoops, forgot to offer a solution. The only real solution is here is to declare your PointFloat struct as a class. In other words, replace "value struct" with "ref class". However, this will force your PointFloat objects to be passed by reference, so keep that in mind. Managed C++ is kinda lame sometimes.
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> Managed C++ is kinda lame sometimes.
Sometimes? :)
0
 
Daniel WilsonAuthor Commented:
Lame -- well, if you're accustomed to real C++, definitely! When I wrote this for .Net 1.1, C++ permitted some things (bridging managed /unmanaged code) that C# & VB did not.

Do I need it managed?  Yes.  This is a control that drops onto Windows Forms.

>>When a managed struct is created, ALL fields within that struct are immediately initialized to their defualt values--in this case, your default constructor is no different than the one generated by the compiler. They will both assign 0.0F to both X and Y.

Are you sure?  Managed Extensions for C++ (C++ for .Net 1.1) did not initialize all variables.  That gave me some really nasty bugs in this project several years ago.  It would work right in the IDE, then work wrong compiled for Release.

>>By the way, you are aware that there is already a float version of a 2-D point in the System.Drawing namespace (within the System.Drawing.dll assembly) called System.Drawing.PointF

Yes, I am.  I'll probably use that.  I really don't know what I didn't when I wrote this for 1.1.  I may have been unaware of the class at the time.


0
 
mrjoltcolaCommented:
Not lame if you know what you are dealing with. It is nice of Microsoft to provide us with so many non-standard languages to choose from to keep us from getting too comfortable with cross-platform freedom, like Java or pure C++, however, if you are writing GUIs, trying to be cross-platform ends up making your app LOOK like cross-platform, ie. Java swing apps or Tk apps, or even Qt.

I say, if you are gonna go GUI on Windows, go all in!

But regarding managed C++, when I'm writing for .NET, I choose not to introduce C++ at all, and stick with C#. Otherwise, I'd just prefer to stick with MFC if I'm going to be tracking down C++ problems and managing my memory.

I assume in this case you had reasons, such as a .NET app that had a requirement for something native?
0
 
evilrixSenior Software Engineer (Avast)Commented:
I'm not really down with this managed C++ nonsense, so I'm waiting for mrjoltcola to shoot this down in flames but can't you just have an unmanaged struct and if it needs to be passed into a managed function just wrap it in a managed struct?

Frankly, I just fail to see why Microsoft insist on making life hard for C++ programmers by keep on modifying the semantics of well defined C++ constructs. :(

mrjoltcola... fire away :)
using namespace System;
 
struct foo
{
	foo () : n(0){}
	int n;
};
 
value struct foowrapper
{
	foowrapper(foo & f) : f(f){}
	foo & f;
};
 
void bar(foowrapper ^ f)
{
	f->f.n = 1;
}
 
void bar(foo & f)
{
	f.n = 1;
}
 
int main(array<System::String ^> ^args)
{
	foo f;
	foowrapper fw(f);
 
	bar(f);
	bar(fw);
}

Open in new window

0
 
mrjoltcolaCommented:
I was ready to load up, looking for my bullets, but I think the wrapper is fine, except we don't really know why the OP wants a value type in the first place, so we won't know if this wrapper will solve anything.

He could just use a single managed class instead, in that case, but I assume since he chose not to, that he wants the value type / call by value semantics for performance or interop reasons.
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> so we won't know if this wrapper will solve anything.
That's true... although I think I was throwing it out there more for my interest than anything else :)
0
 
Daniel WilsonAuthor Commented:
Honestly, I can't remember why I wrote it that way under .Net 1.1.  Of course it was a __gc struct ... or something like that back then.
0
 
evilrixSenior Software Engineer (Avast)Commented:
Ooh, my speculative question became an assisted answer :)
0
 
mrjoltcolaCommented:
With an A+ no doubt!
0
 
Daniel WilsonAuthor Commented:
Good discussion of the issue is, to me, valuable assistance.  Of course it wasn't the solution ... but it is valuable.

Thanks to all of you.  If I run into more C++/CLI grief on this project, I'm hoping you see my questions!
0
 
tcullerCommented:
I wasn't trying to rag on Microsoft -- yes, it was great of them to supply a Managed version of C++; I was merely saying it can often be extremely lame :/

Yeah, it *should* initialize all fields to their default values in the default constructor. Keep in mind that reference types' default values are null, not their default constructor (if one is present).
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 5
  • 4
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now