x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

GENERATED_BODY() causing function declaration and member inaccessibility errors

I have declared a copy constructor and an assignment operator (=) for a class in the .h file and defined it in the .cpp file. On building, the compiler throws an error saying "UCGenome::UCGenome(const UCGenome& g) member function already defined or declared" (for the copy constructor, similar error for assignment operator too), followed by a note that says "see declaration of UCGenome::UCGenome" and points to the line GENERATED_BODY(). I am pretty sure I have declared the function only once in the in the .h file. What am I supposed to do to fix this? Moreover, on creating an object of the UCGenome class in another file, I am unable to access the private members of the class. The assignment operator is unable to access private members. Kindly provide a fix for this too.

Product Version: UE 4.15
Tags:
more ▼

asked Mar 25 '17 at 06:06 AM in C++ Programming

avatar image

sidwakesup
10 4 6 6

(comments are locked)
10|2000 characters needed characters left

2 answers: sort voted first

The GENERATED_BODY() macro probably already defines the copy constructor and assignment operator. Since UE4 has its own system of life cycle built onto the C++ way to do things you can't do stuff exactly as you would in standalone c++ code. I don't know what exactly you would do in an assignment operator (other than the stock behaviour of course), but you can check this out for more information on copy construction. You can of course always just use normal methods to achieve things if the operators are already taken, but as I said, I don't know with what kind of behaviour you would extend the assignment operator: If you just want the "normal" behaviour know: It is already defined for you.

more ▼

answered Mar 25 '17 at 09:31 AM

avatar image

pulp_user
1.2k 46 29 58

avatar image sidwakesup Mar 25 '17 at 09:46 AM

I am using the assignment operator to equate two objects of class UCGenome. So basically by saying object1 = object2, I want to assign the values of member variables of object2 to the corresponding members of object1.

avatar image pulp_user Mar 25 '17 at 11:02 AM

Ok so this is just standard behaviour. I did a bit of research myself, and it seems like the GENERATED_BODY() macro declares the method, but does not define it. So you should be fine by just deleting the declaration in your .h file, but leaving the definition in your .cpp file.

avatar image sidwakesup Mar 25 '17 at 12:38 PM

Thank you for the reply. I removed the declarations of the copy constructor and assignment operator from the .h file. This eliminated the multiple declaration error. But the error of inaccessibility of private member still persists. " 'UCGenome::operator =' cannot access private member declared in class 'UCGenome' " This is the error i get. Similarly for the copy constructor I get " 'UCGenome::UCGenome' cannot access private member declared in class 'UCGenome' ".

How do I fix this?

avatar image pulp_user Mar 25 '17 at 12:51 PM

Please post your code so I can take a look at it.

avatar image sidwakesup Mar 25 '17 at 01:10 PM

I am unable to attach .cpp and .h files here. And the code is too long to post here. Is it possible to email the code to you? Kindly share your email id and I shall immediately mail the files in question. Thank you.

avatar image pulp_user Mar 25 '17 at 01:26 PM

When you write a comment there are several symbols above the window where you type. The one with the ones and zeros is specifically for posting code. You can paste your stuff in there.

avatar image sidwakesup Mar 25 '17 at 01:27 PM

Yeah but it's causing the number of characters to exceed the limit.

avatar image pulp_user Mar 25 '17 at 01:30 PM

just paste your definition of the assignment operator in there. I don't need your whole class :D

avatar image sidwakesup Mar 25 '17 at 01:32 PM
 //------------------------------------------------------------
 //Copy Constructor
 //------------------------------------------------------------
 UCGenome::UCGenome(const UCGenome& g)
 {
     m_GenomeID = g.m_GenomeID;
     m_vecNeurons = g.m_vecNeurons;
     m_vecLinks = g.m_vecLinks;
     m_pPhenotype = NULL;    //no need to perform a deep copy
     m_fFitness = g.m_fFitness;
     m_fAdjustedFitness = g.m_fAdjustedFitness;
     m_iNumInputs = g.m_iNumInputs;
     m_iNumOutputs = g.m_iNumOutputs;
     m_fAmountToSpawn = g.m_fAmountToSpawn;
 }
 
 //------------------------------------------------------------
 //Assignment Operator
 //------------------------------------------------------------
 UCGenome& UCGenome::operator =(const UCGenome& g)
 {
     //self assignment guard
     if (this != &g)
     {
         m_GenomeID = g.m_GenomeID;
         m_vecNeurons = g.m_vecNeurons;
         m_vecLinks = g.m_vecLinks;
         m_pPhenotype = NULL;    //no need to perform a deep copy
         m_fFitness = g.m_fFitness;
         m_fAdjustedFitness = g.m_fAdjustedFitness;
         m_iNumInputs = g.m_iNumInputs;
         m_iNumOutputs = g.m_iNumOutputs;
         m_fAmountToSpawn = g.m_fAmountToSpawn;
     }
 
     return *this;
 }
avatar image pulp_user Mar 25 '17 at 01:40 PM

Can you also post your headerfile? (at least the part with variables). Your code looks ok, the only thing that comes to my mind is that maybe one of your members doesn't have an assignment operator defined. This may cause the error.

avatar image sidwakesup Mar 25 '17 at 02:05 PM

This is all the private members of the class.

private:

     //its identification number
     int m_GenomeID;
 
     //all the neurons which make up this genome
     TArray<FNeuronGene> m_vecNeurons;
 
     //and all the links
     TArray<FLinkGene> m_vecLinks;
 
     //pointer to its phenotype
     UCNeuralNet* m_pPhenotype;
 
     //the depth of this genome's network
     int m_iNetDepth;
 
     //its raw fitness score
     float m_fFitness;
 
     //its fitness score after it has been placed into a
     //species and adjusted accordingly
     float m_fAdjustedFitness;
 
     //the number of offpsprings this individual is required
     //to spawn for the next generation
     float m_fAmountToSpawn;
 
     //keeps a record of the number of inputs and outputs
     int m_iNumInputs;
     int m_iNumOutputs;
 
     //keeps a track of which species this genome is in
     int m_iSpecies;
 
     //returns true if the specified link is already part of the genome
     bool DuplicateLink(int NeuronIn, int NeuronOut);
 
     //given a neuronid this function just finds its position in m_vecNeurons
     int GetElementPos(int neuron_id);
 
     //tests if the passed ID is the same as any existing neuron IDs.
     //Used in AddNeuron
     bool AlreadyHaveThisNeuronID(const int ID);
avatar image sidwakesup Mar 25 '17 at 02:07 PM

Public members shown below

 public:
 
     UCGenome();

     UCGenome(int id, int inputs, int outputs);

     UCGenome(int id,
         TArray<FNeuronGene> neurons,
         TArray<FLinkGene> genes,
         int inputs,
         int outputs);
 
     ~UCGenome();
 
     //copy constructor
 //    UCGenome(const UCGenome& g);
 
     //assignment operator
 //    UCGenome& operator =(const UCGenome& g);
 
     UFUNCTION(BlueprintCallable, Category = NEAT)
         UCNeuralNet* CreatePhenotype();
 
     UFUNCTION(BlueprintCallable, Category = NEAT)
         void DeletePhenotype();

     UFUNCTION(BlueprintCallable, Category = NEAT)
         void InitializeWeights();

         void AddLink(float MutationRate,
             float ChanceOfRecurrent,
             UCInnovation &innovation,
             int NumTrysToFindLoop,
             int NumTrysToAddLink);

         void AddNeuron(float MutationRate,
             UCInnovation &innovation,
             int NumTrysToFindOldLink);
 
     UFUNCTION(BlueprintCallable, Category = NEAT)
         void MutateWeights(float mut_rate,
             float prob_new_mut,
             float fMaxPerturbation);
 
     UFUNCTION(BlueprintCallable, Category = NEAT)
         void MutateActivationResponse(float mut_rate,
             float MaxPerturbation);
 
     float GetCompatibilityScore(const UCGenome &genome);
 
     UFUNCTION(BlueprintCallable, Category = NEAT)
     void SortGenes();
 
     bool Write(ostream &file);
         bool CreateFromFile(const char* szFileName);
 
     //overload '<' used for sorting. From fittest to poorest
     friend bool operator <(const UCGenome& lhs, const UCGenome& rhs)
     {
         return (lhs.m_fFitness > rhs.m_fFitness);
     }
avatar image pulp_user Mar 25 '17 at 02:10 PM

So do you have assignment operators /copy constructors for UCNeuralNet FLinkGene and FNeuronGene?

avatar image sidwakesup Mar 25 '17 at 02:12 PM

No. The errors are not occurring with UCNeuralNet objects. They're occurring with UCGenome objects.

error C2248: 'UCGenome::operator =': cannot access private member declared in class 'UCGenome'

avatar image pulp_user Mar 25 '17 at 02:31 PM

on which line does that error happen?

avatar image sidwakesup Mar 25 '17 at 02:36 PM

The error occurs on multiple lines. For example, the copy constructor error occurs for this line and the constructor definition in another file called CSpecies

 UCGenome Leader()const { return m_Leader; }

 UCSpecies::UCSpecies(UCGenome &FirstOrg,
     int SpeciesID) :m_iSpeciesID(SpeciesID),
     m_fBestFitness(FirstOrg.Fitness()),
     m_iGensNoImprovement(0),
     m_iAge(0),
     m_Leader(FirstOrg), //copy constructor error here
     m_fSpawnsRqd(0)
 {
     m_vecMembers.Add(&FirstOrg);
     m_Leader = FirstOrg; //assignment operator error
 }

The error shows up in similar locations in the rest of the file

avatar image pulp_user Mar 25 '17 at 02:57 PM

Ok but where are the errors in your original two methods? It's not really usefull to jump around classes now. Where do the errors occur in the UGenome constructor and assignment operator?

avatar image sidwakesup Mar 25 '17 at 05:05 PM

The errors are not in the definition of these two. The error occurs when I use these methods in other classes. I have another class called UCSpecies which contains a UCGenome object as a member variable. So in various constructors and methods of UCSpecies, I am using the copy constructor and assignment operator of UCGenome to set the value of that member. That's where the errors are thrown.

avatar image sidwakesup Mar 25 '17 at 05:18 PM
 UCSpecies::UCSpecies(UCGenome &FirstOrg,
     int SpeciesID) :m_iSpeciesID(SpeciesID),
     m_fBestFitness(FirstOrg.Fitness()),
     m_iGensNoImprovement(0),
     m_iAge(0),
     m_Leader(FirstOrg), //copy constructor error
     m_fSpawnsRqd(0)
 {
     m_vecMembers.Add(&FirstOrg);
     m_Leader = FirstOrg; //assignment operator error
 }
 
 void UCSpecies::AddMember(UCGenome &NewMember)
 {
     if (NewMember.Fitness() > m_fBestFitness)
     {
         m_fBestFitness = NewMember.Fitness();
         m_iGensNoImprovement = 0;
         m_Leader = NewMember; //assignment operator error
     }
 
     m_vecMembers.Add(&NewMember);
 }
 
 UCGenome UCSpecies::Spawn()
 {
     UCGenome baby;
 
     if (m_vecMembers.Num() == 1)
     {
         baby = *m_vecMembers[0]; //assignment operator error
     }
     else
     {
         int MaxIndexSize = (int)(UCParams::fSurvivalRate * m_vecMembers.Num()) + 1;
         int TheOne = RandomInt(0, MaxIndexSize);
         baby = *m_vecMembers[TheOne]; //assignment operator error
     }
 
     return baby; //copy constructor error
 }
avatar image sidwakesup Mar 25 '17 at 05:19 PM

It is assuming the copy constructor and the assignment operator to be private members which is probably why it is unable to access them. But a constructor should obviously be a public member right?

avatar image pulp_user Mar 25 '17 at 05:25 PM

Oh yeah that is the problem. So I told you about custom lifecycle management in ue4 earlier. This is part of it. Since you don't use new and delete in unreal, the constructors are not public. You use methods like NewObject and such to instantiate new stuff. It has to do with memory management, unreal allocates memory on its own instead of using the standard C++ way. It makes memory allocation way faster.

So no, you can't simply call the constructor. It gets called by NewObject and similar methods. Check this out for further information and a workaround.

avatar image sidwakesup Mar 25 '17 at 05:51 PM

So I basically need to change the way I am defining the copy constructor as well as its usage. I am unable to understand the parameters of the copy constructor declaration provided in the link. Could you kindly explain how that syntax applies to my case?

avatar image pulp_user Mar 25 '17 at 06:08 PM

I posted my comment as a new anser, since this comment tree is getting rather annoying to read (its so small now).

avatar image sidwakesup Mar 27 '17 at 01:50 AM

is there any way to check ue4's implementation of copy constructors and assignment operators? Also, how do i eliminate the error of the inaccessibility of class members. I am creating an object of class UCGenome in another class UCSpecies. But this object is unable to access its own members. Even though I have declared the constructors and assignment operators in pubic scope, it considers it to be a private member.

(comments are locked)
10|2000 characters needed characters left

First of all: you can find the definition of NewObject in UObjectGloabs.h:1221 this is its full signature:

     T* NewObject(UObject* Outer, UClass* Class, FName Name = NAME_None, EObjectFlags Flags = RF_NoFlags, UObject* Template = nullptr, bool bCopyTransientsFromClassDefaults = false, FObjectInstancingGraph* InInstanceGraph = nullptr)

So the signature works as follows:

  • Outer: the outer object can be any object. It is used to determine the lifecycle and how it will be saved, to my knowledge. (If you created a component you would probably use the actor that the component should stick to as the outer)

  • Class: this is used to spawn blueprint classes. If you just use a c++ class, you can just use YourClass::StaticClass() as this argument.

  • Name: is simply the name it will have. This will be the name you will see when inspecting it in the world outliner for example. you don't have to name it

  • Flags: The definition reveals that this is some very low level stuff. I never used this.

  • Template: This is the object that you want to copy construct from

  • bCopyTransientsFromClassDefaults: No idea

  • InInstanceGraph: No Idea

The baseline is: all the "No Ideas" have default values, so just use those default values.

more ▼

answered Mar 25 '17 at 06:08 PM

avatar image

pulp_user
1.2k 46 29 58

avatar image sidwakesup Mar 25 '17 at 06:28 PM

The function in which I want to call the copy constructor has the template passed as a parameter by reference. Would that cause problems?

avatar image pulp_user Mar 25 '17 at 06:37 PM

no. You would simply use the & operator to get the adress of the reference.I would encourage you to just try it and see if you get any errors. You can just substitute one call at a time and see what happens.

avatar image sidwakesup Mar 25 '17 at 06:36 PM

This is what I tried:

         m_Leader = NewObject(this, UCGenome::StaticClass(), NAME_None, RF_NoFlags, NewMember, false, nullptr);

And the errors I get are this:

2>C:\Users\Siddhant Ravi\Documents\Unreal Projects\Narakasura\Source\Narakasura\CSpecies.cpp(40): error C2672: 'NewObject': no matching overloaded function found 2>C:\Users\Siddhant Ravi\Documents\Unreal Projects\Narakasura\Source\Narakasura\CSpecies.cpp(40): error C2780: 'T NewObject(UObject ,FName,EObjectFlags,UObject ,bool,FObjectInstancingGraph )': expects 6 arguments - 7 provided 2> c:\program files\epic games\ue_4.15\engine\source\runtime\coreuobject\public\UObject/UObjectGlobals.h(1250): note: see declaration of 'NewObject' 2>C:\Users\Siddhant Ravi\Documents\Unreal Projects\Narakasura\Source\Narakasura\CSpecies.cpp(40): error C2780: 'T NewObject(UObject )': expects 1 arguments - 7 provided 2> c:\program files\epic games\ue_4.15\engine\source\runtime\coreuobject\public\UObject/UObjectGlobals.h(1239): note: see declaration of 'NewObject' 2>C:\Users\Siddhant Ravi\Documents\Unreal Projects\Narakasura\Source\Narakasura\CSpecies.cpp(40): error C2783: 'T NewObject(UObject ,UClass ,FName,EObjectFlags,UObject ,bool,FObjectInstancingGraph *)': could not deduce template argument for 'T' 2> c:\program files\epic games\ue_4.15\engine\source\runtime\coreuobject\public\UObject/UObjectGlobals.h(1221): note: see declaration of 'NewObject'

avatar image pulp_user Mar 25 '17 at 06:43 PM

I suspect NewMember is your reference? You would have to use the & operator to get the adress to that, so try using &NewMember in the function call.

avatar image sidwakesup Mar 25 '17 at 06:47 PM

I tried this:

         m_Leader = NewObject<UCGenome>(&NewMember);

And the error I get now is that it is unable to recognize the '=' operator. I believe NewObject() returns a pointer to the object? From the compile log I can see that that's causing the error as it is not able to do UCGenome = UCGenome*. m_Leader is a UCGenome and NewObject returns UCGenome*.

avatar image pulp_user Mar 25 '17 at 06:53 PM

try m_Leader = *(NewObject < UCGenome>(&NewMember))

We are getting into really basic stuff here, I think you should read some tutorials on C++ pointers and type conversion.

avatar image sidwakesup Mar 25 '17 at 07:07 PM

I did this:

         m_Leader = *(NewObject<UCGenome>(&NewMember));

I had to add the because otherwise it was giving error that it is unable to deduce the type. But now it goes back to the initial error of operator '=' being inaccessible. I have commented out the declaration of the operator in the .h file but it is still giving this error.

I apologize for asking basic questions. Please bear with me.

avatar image pulp_user Mar 25 '17 at 09:47 PM

The convention is to use pointers instead of references. This is very broadly spoken, and there are of course applications for references, but you should probably use a pointer as the argument to you method here, instead of the reference you currently have. I am a bit supprised that I didn't ran into this myself yet. I find that references are usually used for data objects, but all the UObject derived classes are usually referenced by pointers. I would advise you to read a tutorial about them like this for example. I will not post the fix here, because you will easily be able to do it yourself once you are through that tutorial, and you definitely should know about pointers when you want to use C++ in UE. If you are done with that and still have questions you can of course ask again.

(comments are locked)
10|2000 characters needed characters left
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question