Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Cannot access private member declared in class

    SDK Help
    0
    7
    490
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      On 03/03/2014 at 15:28, xxxxxxxx wrote:

      User Information:
      Cinema 4D Version:   13,14,15 
      Platform:   Windows  ;   
      Language(s) :     C++  ;

      ---------
      You experienced C++ guys, who do I get:

      error C2248: 'BaseList2D::BaseList2D' : cannot access private member declared in class 'BaseList2D'

      when I try to compile this code:

      	class ButterFly : public BaseList2D
      	{
      	  private:
      		ButterFly();
      		~ButterFly();
      	  public:
      	};
      

      The Cinema 4D SDK is chock full of classes, derived from the BaseList2D, declaring the class exactly this way. So why do I get this error?

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 03/03/2014 at 22:48, xxxxxxxx wrote:

        You can not create an instance of a class that has a private constructor. There is only
        one situation in which it makes sense to create your own BaseList2D subclass. Imagine
        you have your own NodeData subclass that implements some new features (such as TagData
        and ObjectData do) and you want to provide an API for other people to access internal data
        from this NodeData plugin.

        template<typename Type> inline Type* RetrieveTableX(const GeListNode* obj) {
            NodeData* data = obj->GetNodeData();
            return (Type* ) C4DOS.Bl->RetrieveTableX((NodeData* ) data, 0);
        }
          
        class ButterFly;
          
        class ButterFlyData : public NodeData {
          
        public:
          
            /* Called when ButterFly::SetSomeValue() is called. */
            virtual void SetSomeValue(Float value) {
                // ...
            }
          
        };
          
        struct BUTTERFLYPLUGIN : public NODEPLUGIN {
            void (ButterFlyData::*SetSomeValue)(Float);
        };
          
        class ButterFly : public BaseList2D {
        private:
            ButterFly();
            ~ButterFly();
        public:
          
            void SetSomeValue(Float value) const {  
                ButterFlyData* data = static_cast<ButterFlyData*>(GetNodeData());
                if (!data) return nullptr;
          
                BUTTERFLYPLUGIN* method_table = RetrieveTableX<BUTTERFLYPLUGIN*>(data);
                if (!method_table) return nullptr;
          
                return (data->*method_table->SetSomeValue)(this, value);
            }
          
            static ButterFly* Alloc() {
                return static_cast<ButterFly*>(BaseList2D::Alloc(ID_BUTTERFLY_PLUGIN));
            }
          
            static void Free(ButterFly*& ptr) {
                #ifdef DEBUG
                    if (!ptr) {
                        DiagnosticOutput("Passed nullptr to ButterFly::Free()");
                        DebugStop();
                    }
                    if (!ptr->IsInstanceOf(ID_BUTTERFLY_PLUGIN)) {
                        DiagnosticOutput("Non-Butterfly Plugin node passed to ButterFly::Free()");
                        DebugStop();
                    }
                #endif
                if (ptr) {
                    BaseList2D::Free(ptr);
                }
            }
          
        };
        

        This is very very advanced stuff though.

        Best,
        -Niklas

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 04/03/2014 at 02:49, xxxxxxxx wrote:

          Hi Niklas!
          I try to learn, and your help is invaluable!
          In this case, I would learn much more, if you could take your time to correct the errors I get. 
          I replaced Float by Real, because I got errors (R14 <--> R15)? But that should not influence the code otherwise.

          1) This error is obvious, right? Just remove nullptr.

          2) Here I have no clue

          3) Seems that the error goes away when I remove "this"

          4) If I replace ButterFly* with  BaseList2D*, the error goes away, but I am not sure if that correction is right?

          Ok, any help on this is very welcome, because this is what I learn from!

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 04/03/2014 at 05:07, xxxxxxxx wrote:

            Hi ingvar,

            I'm sorry that I forgot to add that I wrote the example completely from scratch in the plugincafe
            reply editor. I'll give you a corrected version soon, just need to find the time for it.

            I still have a Jetlag, so sorry for the issues. I actually expected it to have more errors.. Tongue

            1. Yes, I originally intended the function to return a pointer and forgot to fix the return statements.
            2. Just grabbed the code from an existing plugin of mine but I didn't see that I actually made a
              second overload for it. Make it
            template<typename Type> inline Type* RetrieveTableX(NodeData* data) {
                return (Type* ) C4DOS.Bl->RetrieveTableX(data, 0);
            }
            
            1. Either remove the this or ass ButterFly* as the first parameter to the SetSomeValue() method.

            2. No, that would lead to an infinite recursive call. I forgot to cas to a BaseList2D reference.

            BaseList2D::Free((BaseList2D*&) ptr)
            

            I won't guarantee that it compiles fine now, though. I think best might be if I give you
            a working example.

            But let me ask you first: Why do you actually want to create a BaseList2D subclass? Any
            special reason for this? As I said above already, it usually makes sense only when you
            want to provide an API to your plugin for other developers.

            Best,
            -Niklas

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 04/03/2014 at 06:58, xxxxxxxx wrote:

              Originally posted by xxxxxxxx

              I won't guarantee that it compiles fine now, though. I think best might be if I give you
              a working example.

              Hi Niklas!
              I got it working!
              Here is code that compiles:

              template<typename Type> inline Type* RetrieveTableX(NodeData* data)
              {
              return (Type* ) C4DOS.Bl->RetrieveTableX(data, 0);
              }
              class ButterFly;
              class ButterFlyData : public NodeData
              {
              private:
              Real _someValue;
               public:
               
              /* Called when ButterFly::SetSomeValue() is called. */
              virtual void SetSomeValue(Real value)
              {
              _someValue = value;
              }
              virtual Real GetSomeValue()
              {
              return _someValue;
              }
                
              static ButterFlyData* NewButterFlyData()
              {
              return gNew ButterFlyData;
              }
              };
              struct BUTTERFLYPLUGIN : public NODEPLUGIN
              {
              void (ButterFlyData::*SetSomeValue)(Real);
              Real (ButterFlyData::*GetSomeValue)();
              };
              class ButterFly : public BaseList2D
              {
               private:
              ButterFly();
              ~ButterFly();
               public:
               
              void SetSomeValue(Real value) const
              {
              ButterFlyData* data = static_cast<ButterFlyData*>(GetNodeData());
              if(!data) 
              return;// nullptr;
              BUTTERFLYPLUGIN* method_table = RetrieveTableX<BUTTERFLYPLUGIN>(data);
              if(!method_table) 
              return;// nullptr;
              return (data->*method_table->SetSomeValue)(value);
              }
              Real GetSomeValue() const
              {
              ButterFlyData* data = static_cast<ButterFlyData*>(GetNodeData());
              if(!data) 
              return -9.9;// nullptr;
              BUTTERFLYPLUGIN* method_table = RetrieveTableX<BUTTERFLYPLUGIN>(data);
              if(!method_table) 
              return -9.9;// nullptr;
              return (data->*method_table->GetSomeValue)();
              }
                
              static ButterFly* Alloc()
              {
              return static_cast<ButterFly*>(BaseList2D::Alloc(ID_BUTTERFLY_PLUGIN));
              }
              static void Free(ButterFly* &ptr)
              {
              #ifdef DEBUG
              if(!ptr)
              {
              DiagnosticOutput("Passed nullptr to ButterFly::Free()");
              DebugStop();
              }
              if(!ptr->IsInstanceOf(ID_BUTTERFLY_PLUGIN))
              {
              DiagnosticOutput("Non-Butterfly Plugin node passed to ButterFly::Free()");
              DebugStop();
              }
              #endif
              if(ptr)
              {
              BaseList2D::Free((BaseList2D*&)ptr);
              }
              }
              };
              

              But I have this issue now, I cannot Register it:

              1. Bool b = RegisterNodePlugin(ID_BUTTERFLY_PLUGIN, "butterfly", PLUGINFLAG_HIDE
              2. , (NodeData* )ButterFlyData::NewButterFlyData
              3. , NULL, 0, 0);
              

              Line 2, have no idea how to write a DataAlloctator that will satisfy the compiler.
              So I am stuck here. Can you help me out here? When this compiles, I think I have it!

              Originally posted by xxxxxxxx

              But let me ask you first: Why do you actually want to create a BaseList2D subclass? Any
              special reason for this? As I said above already, it usually makes sense only when you
              want to provide an API to your plugin for other developers.

              Can we make a deal? When it compiles, and registers properly, so that I can use it, I will tell you. Ok?

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                On 04/03/2014 at 08:34, xxxxxxxx wrote:

                Oh my gosh, this has never happened to me before. I accidentally edited your post instead of
                posting my own, ingvar! I'm so sorry! Very emberassing..

                Edit: Phew! your post was still in my browser history!

                > Can we make a deal?

                All right! Pass ButterflyData::NewButterflyData() as the Data Allocator. if that doesn't work
                right away, create the same function again but make it return NodeData* instead.

                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  On 04/03/2014 at 09:34, xxxxxxxx wrote:

                  Originally posted by xxxxxxxx

                  Oh my gosh, this has never happened to me before. I accidentally edited your post instead of
                  posting my own, ingvar! I'm so sorry! Very emberassing.. 
                  Edit: Phew! your post was still in my browser history!

                  No problem, I have almost no idea about what you are talking about, almost like reading the C4D SDK..  
                  You are a moderator, so your duty is to edit other's posts, isn't it? !Big smile[URL-REMOVED]

                  Originally posted by xxxxxxxx

                  All right! Pass ButterflyData::NewButterflyData() as the Data Allocator. if that doesn't work
                  right away, create the same function again but make it return NodeData* instead.

                  Yes, it did not work as you said, and making it return NodeData* works, as you said, but introduces another problem:

                  	void SetSomeValue(Real value) const
                  	{
                  		ButterFlyData* data = static_cast<ButterFlyData*>(GetNodeData());
                  		if(!data) 
                  			return;// nullptr;
                  		
                  		BUTTERFLYPLUGIN* method_table = RetrieveTableX<BUTTERFLYPLUGIN>(data);
                  		if(!method_table) 
                  			return;// nullptr;
                  			
                  		 **// Will crash here** 		
                  		return (data->*method_table->SetSomeValue)(value);
                  	}
                  

                  It will crash, probably because it "believes" it is a pure NodeData, the ancestor, and not the descendant (?).
                  I am almost giving up on this one, but regardless of my intentions with this, I learn a lot, and it would be really interesting to make it work, still.


                  [URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.

                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post