Solved

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

Posted on 2009-05-06
15
1,225 Views
Last Modified: 2012-06-27
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
Comment
Question by:Daniel Wilson
  • 5
  • 4
  • 3
  • +1
15 Comments
 
LVL 40

Expert Comment

by:mrjoltcola
ID: 24321828
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
 
LVL 40

Assisted Solution

by:mrjoltcola
mrjoltcola earned 150 total points
ID: 24321851
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
 
LVL 9

Accepted Solution

by:
tculler earned 300 total points
ID: 24322654
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
 
LVL 9

Expert Comment

by:tculler
ID: 24322661
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
 
LVL 40

Expert Comment

by:evilrix
ID: 24322963
>> Managed C++ is kinda lame sometimes.
Sometimes? :)
0
 
LVL 32

Author Comment

by:Daniel Wilson
ID: 24325740
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
 
LVL 40

Expert Comment

by:mrjoltcola
ID: 24327371
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 40

Assisted Solution

by:evilrix
evilrix earned 50 total points
ID: 24327655
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
 
LVL 40

Expert Comment

by:mrjoltcola
ID: 24327854
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
 
LVL 40

Expert Comment

by:evilrix
ID: 24327881
>> 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
 
LVL 32

Author Comment

by:Daniel Wilson
ID: 24327895
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
 
LVL 40

Expert Comment

by:evilrix
ID: 24327940
Ooh, my speculative question became an assisted answer :)
0
 
LVL 40

Expert Comment

by:mrjoltcola
ID: 24327955
With an A+ no doubt!
0
 
LVL 32

Author Comment

by:Daniel Wilson
ID: 24328037
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
 
LVL 9

Expert Comment

by:tculler
ID: 24331225
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

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now