Dziwne zachowanie podczas dziedziczenia.

0

Problem dotyczy c++cli. Mój projekt wygląda tak, że jest w nim klasa Form1 wewnątrz której są klasy GenerateControls oraz GenerateLabels. Obie klasy są szablonowe. Próbowałem zrobić tak, aby każda z tych dwóch była w osobnym projekcie, jednak wyskakiwały błędy.

1>Trening.obj : error LNK2020: unresolved token (06000014) Trening.GenerateControls<System::Windows::Forms::TextBox>::set_Size
1>Trening.obj : error LNK2020: unresolved token (06000015) Trening.GenerateControls<System::Windows::Forms::TextBox>::get_Size
1>Trening.obj : error LNK2020: unresolved token (06000016) Trening.GenerateControls<System::Windows::Forms::TextBox>::get_Tablica
1>Trening.obj : error LNK2020: unresolved token (06000017) Trening.GenerateControls<System::Windows::Forms::TextBox>::Dispose
1>Trening.obj : error LNK2020: unresolved token (06000018) Trening.GenerateControls<System::Windows::Forms::TextBox>::Dispose 

Jako, że nie miałem doświadczenia w dodawaniu klas pomyślałem, że może coś źle robię i póki nie znajdę problemu będę działać na tych zagniezdżonych klasach. Jednak i tutaj pojawił się ten sam problem pomimo, iż wszystko wcześniej działało tak jak należy. Okazało się, że problem wywołuje najprawdopodobniej dziedziczenie po klasie GenerateControls oraz brak inicjalizacji obiektu. Oznacza to, że jeżeli są same deklaracje i definicje klas wszystko jest ok, natomiast jeśli dodamy jakieś obiekty tych klas zaczynać sypać błędami jak powyżej. I nie było by w tym nic dziwnego gdyby nie to, że jak dodamy kod który znajduje się w funkcji InitializeComponent to wszystko zaczyna nagle działać. O co tu chodzi?

Całość wygląda mniej więcej tak (to skopiowałem tylko wybrane fragmenty)

namespace Trening 
{
    public ref class Form1 : public System::Windows::Forms::Form
	{
	public:
		Form1(void)
		{
			InitializeComponent();
		}
        template <class T>
        ref class GenerateControls;

        template <class T>
        ref class GenerateLabels;
		
        typedef System::Windows::Forms::Label Label;
        typedef System::Windows::Forms::TextBox TextBox;
 
        GenerateLabels< Label > ^ labels;
        GenerateControls< TextBox > ^ textbox;
     
        void InitializeComponent(void)
	{

             labels = gcnew GenerateLabels< Label >(10,20,80,0,30,"lab",35,20);
             textbox = gcnew GenerateControls< TextBox >(10,85,80,0,30,"textbox",145,35);

             this->Controls->AddRange(labels->Tablica);
			
             this->Controls->AddRange(textbox->Tablica);
        }


	GenerateControls(int i , int j, int k,int l, int m, String ^ n, int o, int p)
		: size(i),x(j),y(k),rozstawx(l),rozstawy(m), name(n), sizex(o), sizey(p)
		{
			tablica = gcnew array < T ^ >(size);

			for ( int j = 0 ; j < i ; ++j)
			{
				tablica[j] = gcnew T();	
				tablica[j]->Name = String::Concat(n,Convert::ToString(j));
				tablica[j]->Location = System::Drawing::Point(x+rozstawx*j,y+rozstawy*j);
				tablica[j]->Size = System::Drawing::Size(sizex,sizey);
				tablica[j]->Visible = true;
			}
		}
		~GenerateControls()
		{
			for ( int j = 0 ; j < size ; ++ j )
			{
			}
		}
	

	property int Size
	{
		void set(int value)
		{
			//if(value < 1 ) throw
			size=value;
		}
		int get()
		{
			return size;
		}
	}
	property array< T ^ > ^ Tablica
	{
		array<T ^ > ^ get()
		{
			return tablica;
		}
	}
	
	void SetVisible ( int i)
	{
		for( int j = 0 ; j < size ; ++j)
		{
			if ( j < i ) tablica[j]->Visible = true;
			else tablica[j]->Visible = false;
		}

	}
	
	void SetPosition( int x, int y, int odleglosc_x, int odleglosc_y, int ile)
	{
		//if (ile > Size ) throw 
		for ( int i = 0 ; i<ile ; ++i)
		{
			Tablica[i]->Location = System::Drawing::Point(x+odleglosc_x*i,y+odleglosc_y*i);
		}
	}

	void SetSize( int x, int y, int ile)
	{
		// if (ile > Size ) throw
		for ( int i = 0 ; i < ile ; ++i)
		{
			Tablica[i]->Size = System::Drawing::Size(x, y);
		}
	}

	private:
		array < T ^ > ^ tablica;
		int size;
		int x;
		int y;
		int rozstawx;
		int rozstawy;
		int sizex;
		int sizey;
		String  ^ name;

	};

	template < class T >
	ref class GenerateLabels : public GenerateControls< T > //: public SetControlText< T >
	{
		public:
	
    	GenerateLabels(int i , int j, int k,int l, int m, String ^ n, int o, int p)
		:GenerateControls( i,j,k,l,m,n,o,p)
		{
			for ( int j = 0 ; j < i ; ++j)
			{
				Tablica[j]->AutoSize = true;
			}
		}
		~GenerateLabels()
		{
		}

		void SetText( array< String ^ > ^ name)
		{
			int i = 0;
			//if (name.Size != controlarray.Size ) throw 
			for each ( String ^ str in name)
			{
				Tablica[i++]->Text = str;
			}
		}

	};
    };
}
0

A gdzie klasa GenerateControls ??? Wklej dokładnie ten kod, który kompilujesz.

0

Teraz sytuacja nieco uległa zmianie. Obie klasy są w jednym pliku nagłówkowym ConGen o rozszerzeniu .h (chciałem aby każda miała swój osobny ale na razie wykombinowałem tak ).

Oto kod tego pliku.

 
#ifndef ConGen
#define ConGen


using namespace System;
namespace Trening
{
	template <class T> 
	ref class GenerateControls
	{

	public:
		GenerateControls(int i , int j, int k,int l, int m, String ^ n, int o, int p)
		: size(i),x(j),y(k),rozstawx(l),rozstawy(m), name(n)//, sizex(o), sizey(p)
		{
			tablica = gcnew array < T ^ >(size);

			for ( int j = 0 ; j < i ; ++j)
			{
				tablica[j] = gcnew T();	
				tablica[j]->Name = String::Concat(n,Convert::ToString(j));
				tablica[j]->Location = System::Drawing::Point(x+rozstawx*j,y+rozstawy*j);
				//tablica[j]->Size = System::Drawing::Size(sizex,sizey);
				tablica[j]->AutoSize = true;
				tablica[j]->Visible = true;
			}

		}
		~GenerateControls()
		{
			//for ( int j = 0 ; j < size ; ++ j )
			//{
			//}
		}
	

	property int Size
	{
		void set(int value)
		{
			//if(value < 0 ) throw
			size=value;
		}
		int get()
		{
			return size;
		}
	}
	property array< T ^ > ^ Tablica
	{
		array<T ^ > ^ get()
		{
			return tablica;
		}
	}
	
	void SetVisible ( int i)
	{
		for( int j = 0 ; j < size ; ++j)
		{
			if ( j < i ) tablica[j]->Visible = true;
			else tablica[j]->Visible = false;
		}

	}
	
	void SetPosition( int x, int y, int odleglosc_x, int odleglosc_y, int ile)
	{
		for ( int i = 0 ; i<ile ; ++i)
		{
			Tablica[i]->Location = System::Drawing::Point(x+odleglosc_x*i,y+odleglosc_y*i);
		}
	}

	void SetSize( int x, int y, int ile)
	{
		// if (ile > Size ) throw
		for ( int i = 0 ; i < ile ; ++i)
		{
			Tablica[i]->Size = System::Drawing::Size(x, y);
		}
	}

	private:
		array < T ^ > ^ tablica;
		int size;
		int x;
		int y;
		int rozstawx;
		int rozstawy;
		int sizex;
		int sizey;
		String  ^ name;

	};

	#include "ConGen.h" // skopiowałem poprzez crtl + a całą klasę i zapomniałem usunąć tej linijki.
using namespace System;

template < class T >
	ref class GenerateLabels : public GenerateControls< T > //: public SetControlText< T >
	{
		public:
	
    	GenerateLabels(int i , int j, int k,int l, int m, String ^ n, int o, int p)
		:GenerateControls( i,j,k,l,m,n,o,p)
		{
		}
		~GenerateLabels()
		{
		}

		void SetText( array< String ^ > ^ name)
		{
			int i = 0;
			//if (name.Size != controlarray.Size ) throw 
			for each ( String ^ str in name)
			{
				Tablica[i++]->Text = str;
			}
		}

	};
}
#endif

Klasa ta jest używana w kilku oknach więc wkleję to ostatnie.


#pragma once
#include "ConGen.h"

namespace Trening {

	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Data::SqlClient;
	using namespace System::Drawing;
	
	
	public ref class okno2 : public System::Windows::Forms::Form
	{
	public:
		okno2(void)
		{
			InitializeComponent();
		}

	protected:

		~okno2()
		{
			if (components)
			{
				delete components;
			}
		}

	private:

	System::ComponentModel::Container ^components;
		
	System::Windows::Forms::TabControl ^ tabcontrol;
	System::Windows::Forms::TabPage ^ tabpage1;
	System::Windows::Forms::TabPage ^ tabpage2;
	System::Windows::Forms::TabPage ^ tabpage3;

	System::Data::SqlClient::SqlConnection ^ sqlcon;

	GenerateControls < System::Windows::Forms::TextBox > ^ tb1;
	GenerateControls < System::Windows::Forms::TextBox > ^ tb2;
	GenerateControls < System::Windows::Forms::TextBox > ^ tb3;

	GenerateLabels < System::Windows::Forms::Label > ^ lb1;
	GenerateLabels < System::Windows::Forms::Label > ^ lb2;
	GenerateLabels < System::Windows::Forms::Label > ^ lb3;

	array < String ^ > ^ stringtabs1;
	array < String ^ > ^ stringtabs2;
	array < String ^ > ^ stringtabs3;

	array < String ^ > ^ textboxtabs1;
	array < String ^ > ^ textboxtabs2;
	array < String ^ > ^ textboxtabs3;

	int clientwidth;
	int clientheight;


#pragma region Windows Form Designer generated code

		void InitializeComponent(void)
		{

			clientwidth = 300;
			clientheight = 300;

			this->tabcontrol = gcnew System::Windows::Forms::TabControl();
			this->tabpage1 = gcnew System::Windows::Forms::TabPage();
			this->tabpage2 = gcnew System::Windows::Forms::TabPage();
			this->tabpage3 = gcnew System::Windows::Forms::TabPage();

			this->tabcontrol->SuspendLayout();
			this->tabpage1->SuspendLayout();
			this->tabpage2->SuspendLayout();
			this->tabpage3->SuspendLayout();

			// tabcontrol

			this->tabcontrol->Alignment = System::Windows::Forms::TabAlignment::Top;
			this->tabcontrol->Controls->Add(this->tabpage1);
			this->tabcontrol->Controls->Add(this->tabpage2);
			this->tabcontrol->Controls->Add(this->tabpage3);
			this->tabcontrol->Dock = System::Windows::Forms::DockStyle::Fill;
			this->tabcontrol->HotTrack = true;
			this->tabcontrol->Location = System::Drawing::Point(0,0);
			this->tabcontrol->Multiline = true;
			this->tabcontrol->Name = L"tabcontrol";
			this->tabcontrol->SelectedIndex = 0;
			this->tabcontrol->ShowToolTips = true;
			this->tabcontrol->Size = System::Drawing::Size(215,129);
			this->tabcontrol->TabIndex =1;

			// tb1 & lb1

			tb1 = gcnew GenerateControls< System::Windows::Forms::TextBox >(10,85,80,0,30,"tb1",145,35);
			//lb1 = gcnew GenerateLabels< System::Windows::Forms::Label >(10,20,80,0,30,"lb1",35,20);     <----------------------------- TU
			// tabPage1
			
			this->tabpage1->BackColor = System::Drawing::Color::PaleGreen;
			this->tabpage1->Controls->AddRange(tb1->Tablica);
			//this->tabpage1->Controls->AddRange(lb1->Tablica);
			this->tabpage1->Location = System::Drawing::Point(4, 4);
			this->tabpage1->Name = L"tabpage1";
			this->tabpage1->Padding = System::Windows::Forms::Padding(3);
			this->tabpage1->Size = System::Drawing::Size(207, 103);
			this->tabpage1->TabIndex = 0;
			this->tabpage1->Text = L"Dane";
			this->tabpage1->ToolTipText = L"Informacje o użytkowniku";
			this->tabpage1->UseVisualStyleBackColor = false;
			
			//tb2 & lb2

			tb2 = gcnew GenerateControls< System::Windows::Forms::TextBox >(10,85,80,0,30,"tb1",145,35);
			//lb2 = gcnew GenerateLabels< System::Windows::Forms::Label >(10,20,80,0,30,"lb1",35,20);     <----------------------------- TU

			// tabPage2
			
			this->tabpage2->BackColor = System::Drawing::Color::Plum;
			this->tabpage2->Controls->AddRange(tb2->Tablica);
			//this->tabpage1->Controls->AddRange(lb2->Tablica);
			this->tabpage2->Location = System::Drawing::Point(4, 4);
			this->tabpage2->Name = L"tabpage2";
			this->tabpage2->Padding = System::Windows::Forms::Padding(3);
			this->tabpage2->Size = System::Drawing::Size(207, 103);
			this->tabpage2->TabIndex = 1;
			this->tabpage2->Text = L"Wymiary";
			this->tabpage2->ToolTipText = L"Wymiary poszczególnych partii";
			this->tabpage2->UseVisualStyleBackColor = false;

			//tb3 & lb3

			tb3 = gcnew GenerateControls< System::Windows::Forms::TextBox >(10,85,80,0,30,"tb1",145,35);
			//lb3 = gcnew GenerateLabels< System::Windows::Forms::Label >(10,20,80,0,30,"lb1",35,20);     <----------------------------- TU
			// tabPage3
			
			this->tabpage3->BackColor = System::Drawing::Color::Plum;
			this->tabpage3->Controls->AddRange(tb3->Tablica);
			//this->tabpage1->Controls->AddRange(lb3->Tablica);
			this->tabpage3->Location = System::Drawing::Point(4, 4);
			this->tabpage3->Name = L"tabpage3";
			this->tabpage3->Padding = System::Windows::Forms::Padding(3);
			this->tabpage3->Size = System::Drawing::Size(207, 103);
			this->tabpage3->TabIndex = 2;
			this->tabpage3->Text = L"Osiągi";
			this->tabpage3->ToolTipText = L"Twoje osiągi";
			this->tabpage3->UseVisualStyleBackColor = false;


			this->Controls->Add(this->tabcontrol);
			this->tabcontrol->ResumeLayout(false);
			this->tabpage1->ResumeLayout(false);
			this->tabpage1->PerformLayout();
			this->tabpage2->ResumeLayout(false);
			this->tabpage2->PerformLayout();
			this->tabpage3->ResumeLayout(false);
			this->tabpage3->PerformLayout();

			this->ResumeLayout(false);

			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->ClientSize = System::Drawing::Size(clientwidth, clientheight);
			this->Name = L"Form1";
			this->Text = L"Form1";
			this->ResumeLayout(false);
		}
#pragma endregion

		private:
//			/*SqlDataReader*/ void Query(String ^ qry)
//			{
//				try
//				{
//					sqlcon = gcnew SqlConnection(L"server=(local)\\SQLExpress;trusted_connection=true;database=Trening");
//					sqlcon->Open();
//
//					if ( sqlcon != nullptr && sqlcon->State == ConnectionState::Open)
//					{
//						String ^ command = L"Select imie from test";
//						SqlCommand ^ sqlcom = gcnew SqlCommand();
//						sqlcom->Connection = sqlcon;
//						sqlcom->CommandType = CommandType::Text;
//						sqlcom->CommandText = String::Format("select * from test");
//
//						SqlDataReader ^ reader = sqlcom->ExecuteReader();
//			
//						tl->Text = "lol";
//						Console::WriteLine("Siema");
////						while (reader->Read)
//						{
////							Console::WriteLine(String::Format("{0} {1}"), reader["imie"], reader["nazwisko"]);
//						}
//					}
//				}
//				catch (System::Exception  ^ exc)
//				{
//						System::Windows::Forms::MessageBox::Show( L"Wystąpił błąd podczas łączenia z bazą danych, przepraszamy."+exc->Message, L"Błąd", 
//					System::Windows::Forms::MessageBoxButtons::OK);
//				}
//				finally
//				{
//					sqlcon->Close();
//				}
//		}

	};
}


Kod który jest zaznaczony ( " <----------------------------- TU" ) powoduje powstawanie takich błędów.

1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: tablica): (0x04000033).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: size): (0x04000034).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: x): (0x04000035).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: y): (0x04000036).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: rozstawx): (0x04000037).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: rozstawy): (0x04000038).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: sizex): (0x04000039).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: sizey): (0x0400003a).
1>Trening.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; fields: name): (0x0400003b).
1>Trening.obj : error LNK2022: metadata operation failed (801311D7) : Differing number of fields in duplicated types (Trening.GenerateControls<System::Windows::Forms::Label>): (0x02000005).
1>Trening.obj : error LNK2022: metadata operation failed (8013118B) : Inconsistent implemented interfaces in duplicated types (types: Trening.GenerateControls<System::Windows::Forms::Label>; interfaces: System.IDisposable): (0x09000002).
1>LINK : fatal error LNK1255: link failed because of metadata errors
 

Natomiast jeśli odkomentujemy te 3 linijki wszystko ładnie się kompiluje. Myśle, że problem stanowi klasa GenerateLabels ponieważ instancja klasy GenerateControls może istnieć bez inicjalizacji i nie powoduje żadnych problemów, natomiast pojawienie się obiektu klasy GenerateLabels, który nie jest później inicjalizowany powoduje te błędy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1