Search code examples
c++c++20unnamed-class

What unnamed calss access rules question On different sub class


Super simple chain store flow statistics logic .

Parent class handle unname Object instance .

Parent class has different sub class .

In a different sub class, access parent class's unname Object, I don't know why the two unname Object are same one.

And I think they are different

Headquarters in China

/*=================> shope.h */
#pragma once

#include <iostream>
#include <string>
using namespace std;

struct {
  string flag = "init value";

  void print(string newFlag) {
    cout << "unnameStruct's adderss:" << this << '\t';
    cout << "flag's address:" << &flag << '\t';
    cout << "rawFlag:" << flag << '\t';
    flag = newFlag;
    cout << "newFlag:" << flag << '\t' << endl;
  }
} unnameStruct;


struct ChinaBaseShop {
  static double turnover; /* income flow */

  virtual void income(double money);
};

/*=================> shope.cpp */
#include "shope.h"

double ChinaBaseShop::turnover = {0.0};
void ChinaBaseShop::income(double money) {
  cout << "ChinaBaseShop's Address : " << this << endl;
  unnameStruct.print("Headquarters in China");
  turnover += money;
}

BeiJing shope

/*=================> beijing_shope.h */
#pragma once

#include "shope.h"

struct BeijingShop : ChinaBaseShop {
  virtual void income(double money) override ;
};


/*=================> beijing_shope.cpp */
#include "beijing_shope.h"

void BeijingShop::income(double money) /* override */ {
  cout << "-BeiJing–" << endl;
  cout << "BeijingShop's Address:" << this << endl;
  unnameStruct.print("BeiJing shope");
  ChinaBaseShop::income(money);
  if(money > 100) {
    /* Over 100 minus 10 */
    turnover -= 10.0;
  }
}

TianJin shope

/*=================> tianjin_shope.h */
#pragma once

#include "shope.h"

struct TianjinShop : ChinaBaseShop {
  virtual void income(double money) override ;
};

/*=================> tianjin_shope.cpp */
#include "tianjin_shope.h"

void TianjinShop::income(double money) /* override */ {
  cout << "-TianJin–" << endl;
  cout << "TianjinShop's Address:" << this << endl;
  unnameStruct.print("TianJin shope ");
  ChinaBaseShop::income(money);
  if(money >= 100) {
      /* over 100 , 10% off */
      turnover -= (money / 10.0);
  }
}

main file

#include "beijing_shope.h"
#include "tianjin_shope.h"

#include <iostream>
using namespace std;

int main() {
  BeijingShop beijingShop;
  TianjinShop tianjinShop;

  cout << "before open any shope : " << ChinaBaseShop::turnover << endl;

  beijingShop.income(20.0);

  cout << "after open BeiJing shope : " << ChinaBaseShop::turnover << endl;

  tianjinShop.income(30.0);

  cout << "after open TianJin shope : " << ChinaBaseShop::turnover << endl;

  return 0 ;
}

Let's look the output :

g++ -std=c++20 -Wall beijing_shope.cpp  main.cpp  shope.cpp  tianjin_shope.cpp -o result.run && ./result.run

before open any shope : 0
-BeiJing–
BeijingShop's Address:0xffffef3323f8
unnameStruct's adderss:0xaaaac85d6108   flag's address:0xaaaac85d6108   rawFlag:init value      newFlag:BeiJing shope
ChinaBaseShop's Address : 0xffffef3323f8
unnameStruct's adderss:0xaaaac85d6160   flag's address:0xaaaac85d6160   rawFlag:init value      newFlag:Headquarters in China
after open BeiJing shope : 20
-TianJin–
TianjinShop's Address:0xffffef3323f0
unnameStruct's adderss:0xaaaac85d6188   flag's address:0xaaaac85d6188   rawFlag:init value      newFlag:TianJin shope 
ChinaBaseShop's Address : 0xffffef3323f0
unnameStruct's adderss:0xaaaac85d6160   flag's address:0xaaaac85d6160   rawFlag:Headquarters in China   newFlag:Headquarters in China
after open TianJin shope : 50

Step 1:

# BeiJing shop instance  and Tianjin Shope instance are different instence , 
# It is reasonable that they are address different
BeijingShop's Address:0xffffef3323f8
TianjinShop's Address:0xffffef3323f0

Setp 2:

# beijing_shope.h include shope.h , tianjin_shope.h include shope.h 
# It is reasonable that on different file unnameStruct's adderss are different 
unnameStruct's adderss:0xaaaac85d6108   flag's address:0xaaaac85d6108   rawFlag:init value      newFlag:BeiJing shope
unnameStruct's adderss:0xaaaac85d6188   flag's address:0xaaaac85d6188   rawFlag:init value      newFlag:TianJin shope 

Step 3:

# On BeijingShop's instance , ChinaBaseShop::this the address is same with BeijingShop's instance . right .
# On TianjinShop's instance , ChinaBaseShop::this the address is same with TianjinShop's instance . right .
ChinaBaseShop's Address : 0xffffef3323f8
ChinaBaseShop's Address : 0xffffef3323f0

Step 4: Not as expected

# I can't understand the output
unnameStruct's adderss:0xaaaac85d6160   flag's address:0xaaaac85d6160   rawFlag:init value      newFlag:Headquarters in China
unnameStruct's adderss:0xaaaac85d6160   flag's address:0xaaaac85d6160   rawFlag:Headquarters in China   newFlag:Headquarters in China

# I think , BeijingShope's instance and TianjinShope's instance are different . 
# So , they super class handle different `unnameStruct` instance . 
# I think the output shoule like this :
unnameStruct's adderss:OneAddress       flag's address:OneAddress       rawFlag:init value      newFlag:Headquarters in China
unnameStruct's adderss:AnotherAddress   flag's address:AnotherAddress   rawFlag:init value      newFlag:Headquarters in China

Anyone will help me? Here's a CMake project @ godbolt.org reproducing the issue.


Solution

  • There is no unnameStruct member in any of your classes, and there is not even any connection between your classes and the "unnameStruct" name.

    A variable of unnamed struct type is implicitly static; if you define struct {} x; in a header and include that header in multiple files, you will find that &x is different in each of those files.

    So you have four different variables called "unnameStruct", one in each translation unit.
    Each income function uses the unnameStruct variable defined in its own translation unit, and you would see yet another result if you added unnameStruct.print("Main"); in main.