4

I have added a class to my program and tested it. I was really surprised that there was any real errors. Here is the code:

#pragma once
#include "Iingredient.h"
#include <string>
#include <vector>

using namespace std;

ref class Recipe{
private:
    string partsName;
    vector<Iingredient> ing;
public:
    Recipe(){}

};

And here are the errors:

Error 23 error C4368: cannot define 'partsName' as a member of managed 'Recipe': mixed types are not supported c:\users\user\documents\visual studio 2010\projects\smestras2_l1\Recipe.h 10 1 file2_L1

Error 24 error C4368: cannot define 'ing' as a member of managed 'Recipe': mixed types are not supported c:\users\user\documents\visual studio 2010\projects\smestras2_l1\Recipe.h 11 1 file2_L1

I googled a bit and found out that its about managed and unmanaged code. How to fix this? Is it related with manged and unmanaged code or not? if so how?

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
Povylas
  • 776
  • 4
  • 16
  • 31

4 Answers4

12

I agree with others: you shouldn't use C++/CLI in most circumstances, you should use C# (or another "normal" managed language) for that (assuming you want to write a .Net application). C++/CLI is useful mostly in special circumstances, like interoperating between managed and unmanaged code.

If you're sure you want use C++/CLI, you can't put native classes into managed ones. But you can put pointers to native classes there:

ref class Recipe{
private:
    string* partsName;
    vector<Iingredient>* ing;
};

The code above works. But you have to keep in mind that those are normal native C++ pointers and that means you have to manually delete them. To do that property, you should read about how destructors and finalizers work in C++/CLI.

svick
  • 236,525
  • 50
  • 385
  • 514
3

You cannot use unmanaged types in a managed class, ref keyword, because the heap and the managed heap are two different types of memory. To solve this specific problem you can use a managed string type (System::String^). The carrot tells the compiler that the type is a handle to a managed class.

Another way of going about this problem is to use pointers, that way the pointer will be on the managed heap, and the actual memory for that object will be in the standard unmanaged heap, which is where Recipe is located.

To construct your Recipe class you would have to do

Recipe^ recipe = gcnew Recipe();
Patrizio Bertoni
  • 2,582
  • 31
  • 43
aj.toulan
  • 1,341
  • 1
  • 16
  • 25
  • if i want to use "System::String^" -> should i use a statement of "include as well at the upperside of the code or should i use a statement "using namespace something" ? @Patrizio.... – gumuruh May 05 '16 at 09:24
3

When defining ref class Recipe, you made it managed. But std::string and std::vector are umanaged types. You are trying to declare native variables in managed class, but it is not allowed.

Seems, you are novice in C++. Just, don't use C++/CLI. Consider C#, if you target .Net or unmanaged C++.

Ed S.
  • 122,712
  • 22
  • 185
  • 265
Lol4t0
  • 12,444
  • 4
  • 29
  • 65
  • 1
    +1 Sound advice to keep out of C++-cli for beginners, it is much more complex than either C# or C++ (which are complex enough on their own) – David Rodríguez - dribeas Feb 14 '12 at 20:36
  • 2
    So to make this work I just need to delete the `ref`to make it a normal C++ class. I used and add class button in visual studio and it generated the class like this, so I thought it had to be correct. Thanks. – Povylas Feb 14 '12 at 20:58
  • what is the usage 'ref' word in-front of class anyway ? @Povylas – gumuruh May 05 '16 at 09:21
1

With no idea of c++-cli, I can try and guess that the problem is that you are defining a reference type and trying to use C++ types inside (a std::string field) rather than whatever the equivalent managed type is (String?).

The reason why this can be problematic is that it mixes resource management approaches. Reference types are intended to be used out of a garbage collector, and unless you implement a destructor or IDisposable will just be ignored once proven that the last reference is lost. On the other hand, to be able to manage the memory in the internal field the std::string destructor must be called.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489