Download

One class contains a TArray of objects of a different class type, compiler says it can't access it.

There are two classes, both of which inherit from AActor. The first is Block. It basically contains a small piece of something. It has no private members. The second is Structure. When a structure loads, it should spawn a lot of Blocks in specific locations. I also want each Structure to have some way to access the specific Blocks it has spawned, in order to do function calls on them. To that end, Structure has a public TArray of ABlocks called blockArray, which should contain all of the Blocks that particular Structure has spawned. Since the SpawnActor function returns a pointer to the actor spawned, I have to add the spawned Block to blockArray through that. I’m cutting some unrelated bits from the code for clarity’s sake, but it looks a bit like this:


UWorld* const World = GetWorld();
if (World) {
  numBlocks = 0;
  while (MoreBlocksToSpawn()) {
    ABlock *tempBlock;
    tempBlock = World->SpawnActor<ABlock>(ABlock::StaticClass(), GetBlockPosition(numBlocks), GetBlockRotation(numBlocks));
    blockArray.Add(*tempBlock);
    numBlocks++;
  }
}

When I try to compile, I get the error:
C2248 ‘ABlock::ABlock’: cannot access private member declared in class ‘ABlock’
The file it lists as the source of the error is Array.h, line 1896. The output elaborates that it also doesn’t like the lines in Block.h where the class is declared and GENERATED_BODY() is used, the line in Structure.cpp where tempBlock is added to blockArray, or the line in Structure.h where blockArray is declared in the first place. Any ideas on what is causing the error, or how to solve it?

Can you post the header for “ABlock”?
It looks like the constructor is declared as protected/private and not public.

HTH

Sure.


#pragma once

#include "GameFramework/Actor.h"
#include "ProceduralMeshComponent.h"
#include "Utility.h"
#include "Block.generated.h"

UCLASS()
class REDACTED_API ABlock : public ABlock {
	GENERATED_BODY()
public:
	ABlock();
	virtual void BeginPlay() override;
	virtual void Tick( float DeltaSeconds ) override;
	void BuildObj(FString filename);
};

hmm, That is strange.
I don’t see a reason for the ABlock to throw a error there.
Can you compile the project from inside visual studio and then post the relevant info from the “output” window(the error and two or three preceding lines) to see if that narrows down the the cause of the error more.

Does it compile if you don’t add the block to the array?

You probably have your array declared as this:


TArray<ABlock> blocksArray;

I deduct this from this line of code as you are dereferencing the pointer before adding it:


blockArray.Add(*tempBlock);

Your array should be storing a pointer to the block:


UPROPERTY()
TArray<ABlock*> blocksArray;

The first declaration is an array of blocks; when you add an item what happens is that the entire block object passed through Add(block) copies the object. ABlock inherits ultimately from UObject and copying those is not allowed as they an UObjects are managed by the garabage collector. The error message you see references the copy constructor, which is made inaccessible in the GENERATED_BODY() macro for reasons mentioned.

Your array should be an array of pointers to ABlocks in order to reference the newly spawned actors. When you then add an item to the array using Add(pBlock) what happens is that the pointer to the block is copied, the memory of the ABlock itself stays the same. Aside from the previously mentioned, I can also deduct that the array isn’t marked as UPROPERTY because the Unreal Header Tool would have complained when it saw the TArray of non-pointers. Make sure you mark the array as UPROPERTY, as the garbage collector will then automatically set “dangling” pointers to destroyed actors to NULL to prevent reading invalid data. Furthermore, marking fields as UPROPERTY has the advantage that the Unreal Header Tool warns you about certain Unreal specific errors.

Declare the Constructor in ABlock under Public, and make sure it’s the ObjectInitializer version too. GENERATED_BODY() defaults everything to private, and also requires you to declare a constructor (whether with or without parameters).

.h



ABlock(const FObjectInitializer& OI);


.cpp



ABlock::ABlock(const FObjectInitializer& OI) : Super(OI)
{}


Oh also, Why is ABlock inheriting from ABlock? That makes no sense. Surely it should be AActor or something? If it is AActor, you can’t have a parameter-less constructor.



class REDACTED_API ABlock : public ABlock


should probably be:



class REDACTED_API ABlock : public AActor


You’re right, ABlock did inherit from AActor, I was just editing the code I posted here a bit to cut out unnecessary parts and keep the names easy to follow, and I made a mistake.

I eventually got this to work by making it a TArray of pointers to ABlocks instead of the ABlocks themselves, and just passing it tempBlock instead of *tempBlock. This will work well enough for my purposes, I think; it’s still able to accept function calls through the pointer.