C# Probleme mit Klassen und Konstruktoren

Abcd12345

Lt. Junior Grade
Registriert
März 2006
Beiträge
483
Hi,

Ich habe mich längere Zeit mal mit C++ beschäftigt speziel mit der Entwiklung von 2D spielen und befasse mich nun aus schulischen Gründen mit C#. Hierzu arbeite ich ein Buch durch.


Ich habe jetzt ein kleines Programm geschrieben. Indem ich eine Basisklasse habe und eine Unterklasse der ich 2 Konstruktoren vererben will. Den Konstruktor ohne Parameterangabe wird ohne Probleme vererbt nur der Konsturktor mit den beiden Parameterangeben kann mit der Subklasse nicht aufgerufen werden.

Code:
using System;

public class CMitarbeiter
{
    protected int m_Lohn;
   
    public string m_sMitarbeitername;

   public CMitarbeiter()
    {
        m_Lohn = 1000;
        m_sMitarbeitername = "unwichtig";

        Console.WriteLine("Konstruktor ohne Parameter wurde aufgerufen");
    }

    public CMitarbeiter(int lohnhöhe, string name )
    {
        m_Lohn = 1000;
        m_sMitarbeitername = name;

        Console.WriteLine("KOnstukrot mit Paramertern wurde aufgerufen");
    }

}

public class CVorarbeiter : CMitarbeiter
{


}

    class Program
    {
        static void Main()
        {

            CMitarbeiter Hans = new CMitarbeiter(1000, "Hans");
            CMitarbeiter Hans2 = new CMitarbeiter();
            CVorarbeiter Hans3 = new CVorarbeiter();
            CVorarbeiter Hans4 = new CVorarbeiter(1000, "Hans");


            
        }
        
            

        
    }

Also 2 Fragen dazu:

Woran liegt es das der Konstruktor mit den 2 Parameterangaben nicht vererbt wird? (ich weis auch nicht mehr ob das in C++ möglich ist vieleicht kann ja auch dazu noch jemand was sagen ;))

Und gibt es eine möglichkeit, wie in C++ einfach einen Teil seiner Klasse in den public Teil und den andern in den protected oder private Teil einzuteilen oder muss ich wirklich vor jede Variabel und Funktion den Sichtbarkeitsspezifer schreiben?
 
1. du hast 2 konstruktoren beim mitarbeiter. wenn du nun nen vorarbeiter machst dann wird immer der parameterlose konstruktor aufgerufen ...

2. einmal public: schreiben und alle darauffolgende deklarierte funktionen sind public ...

public:
funka()
funkb()

protected:
funcc()
... usw also so ists zumindest bei c++ :)
 
zu 1) Müsst ich also den Konstruktor mit den Parameterangaben nochmal in die Subklasse kopieren um dort beider zur Verfügung zu haben oder gibt es da noch eine idealere Lösung?

zu 2) Joar das weis ich auch noch von C++ nur diese Form funktioniert leider bei C# nicht :( und bisher hab ich in dem Buch was ich durcharbeite auch nur die Form gesehen, dass der Gültigkeitsbereich für jedes Element sei es Variabel oder Funktion einzelnt angegeben wird. Ich finde dies sehr umständlich besonders weil ich von C++ anderes gewöhnt bin. Gibt es da nicht eine ähnliche Vorgehensweise wie in C++?
 
ich hab zwar keine ahnung von c#..aber in java gibt es die möglichkeit mit "super" den konstruktor der vererbenden klasse aufzurufen (beispiel in java):
Code:
public class person {
  
  private String wohnort;
  private String name;
  private int alter;
    
    public person(){
      wohnort = "zu hause";
      }

    public person (String n, int a){
        name = n;
        alter = a;
        }
 
//methoden usw.....
}
dann kannst du in deiner abgeleiteten klasse sowas hier machen:
Code:
public class person2 extends person{

     public person2(String n, inta) {
        super(n, a);
        }
//methoden usw....
}

und nach kurzem googlen hab ich herausgefunden dass der c# pendant zu "super" wohl "base" heißt...probiers doch mal damit.
 
Zuletzt bearbeitet: (was vergessen ^^)
Mit base geht das:

Code:
public class Vorarbeiter : Mitarbeiter
{
    public Vorarbeiter()
        : base()
    {
    }

    public Vorarbeiter(int lohnhöhe, string name)
        : base(lohnhöhe, name)
    {
    }
}

Übrigens: In C# benutzt man normalerweise keinen "C"-Prefix vor dem Klassennamen.
 
public class CMitarbeiter {
protected int m_Lohn;
public string m_sMitarbeitername;
public CMitarbeiter() {
m_Lohn = 1000;
m_sMitarbeitername = "unwichtig";
Console.WriteLine("Konstruktor ohne Parameter wurde aufgerufen");
}

public CMitarbeiter(int lohnhöhe, string name ) {
m_Lohn = 1000;
m_sMitarbeitername = name;
Console.WriteLine("KOnstukrot mit Paramertern wurde aufgerufen");
}
}

public class CVorarbeiter : CMitarbeiter {

CVorarbeiter (int lohnhöhe, string name ) : CMitarbeiter(lohnhöhe,name ) {}
}

<- damit gibste die parameter von dem äusseren konstruktor an den inneren grad weiter

kannsts aber auch so machen:

CVorarbeiter ( ) : CMitarbeiter(1000, "unwichtig" ) {}
}


oder beides zusammen in ne klasse tun, konstruktoren sind wie funktionen ... die kann man überladen ... also gleichnamige funktionen die sich nur von den übergabeparametern unterscheiden
 
Sorry bullsh1t, aber das ist Schwachsinn. Konstruktorüberladungen in C# funktionieren nur mit "this" oder "base".

Eine Erweiterung zu meinem Beispiel noch:
Wenn Vorarbeiter z. B immer 1000 € Lohn bekommen, dann kann man das auch mit dem Konstruktor lösen:
Code:
public class Vorarbeiter : Mitarbeiter
{
    public Vorarbeiter(string name)
        : base(1000, name)
    {
    }
}

Um das gemäkel nicht noch weiter auszuweiten ;): Die Microsoft Naming Guidelines sind immer einen Blick wert.
 
Danke für die Hilfe schonmal. Hab jetzt aber noch 2 Probleme

1.Wenn ich jetzt 3 KOnstukroten der Basisklasse habe gibt es auch eine möglichkeit, das die Subklasse alle 3 Konstruktoren zur vérfügung hat oder ist dies nicht möglich?

2. Ich habe bei follgendem Quellcode eine überladene Funktion (es soll möglich sein der Funktion einen int und einen float Wert zu übergeben), das ganze Funktioniert aber anscheinend nur wenn ich es möglich mache einen int und einen Double Wert zu übergeben.

Code:
using System;

public class test
{
    public void Meth1(int Num)
    {
        Console.WriteLine("Der übergebene Wert {0}", Num);
    }

    public void Meth1(float Num)
    {
        Console.WriteLine("Der übergebene Wert {0}", Num);
    }
}

    class Program
    {
        static void Main(string[] args)
        {

            test m = new test();
            m.Meth1(500);
            //m.Meth1(40.42); --------------> Verursacht einen Fehler (geht nur wenn die überladene Funktion einen "double" Wert übergeben bekommen soll)
        }
    }

Gruß Abcd
 
Du weißt schon was eine Float Zahl ist oder?
Eine Float Zahl ist eine Gleitkommazahl.
zB. 1,124424x10³

float y = 4.5f;

versuch mal so

double myDouble = 2006;
float myFloat = 0;
myFloat = (float)myDouble;

m.Meth1(myFloat);

EDIT2: völliger blödsinn
 
Zuletzt bearbeitet:
@Amped: Einen auf Klugscheisser machen und dann nen Komma vorschlagen? oO
Komma trennt Parameter voneinander in einem Methodenaufruf, das kann gar nicht funktionieren.

evtl mal versuchen:
m.Meth1((float)40.42);
 
stimmt
dacht auch grad das da was nit stimmen kann^^

Typecasting hab ich eh vorgeschlagen meister genial
 
Klar hast du das vorgeschlagen, aber irgendwie finde ich deinen Code halt etwas unübersichtlicher... wozu da Variablen deklarieren?
 
Weil es übersichtlicher ist (finde ich),
man sieht es besser heraus das man
aus einer double einen float macht.

Ja man kanns anlegen wie man will,
ich bin mir aber nicht ganz sicher das man

gleich ne zahl casten kann...
schon lang kein C# mehr gemacht...
und in Java gibt es ja das Parseto bzw. auch Casten
in dem das ich nie Float benutze ist es hinfällig
 
Du koenntest auch einfach einen prameter von typ objekt verwenden. Dann sparst dir eine methode ;)

und wg. der faulheit.

es geht auch so
m.Meth1(40.42f); // ist ident mit m.Meth1((float)40.42); nur weniger zu schreiben


und wenn du ein double anstelle des float verwendest sparst dir das casten komplett

EDIT geht auch mit nem grossen F ;)
 
Zuletzt bearbeitet:
Kommt halt drauf an, sicher wenn du sie als
Typ Object nimmst braucht er nur 1. Methode.

Aber vlt will er ja nur Float oder Int ausgeben --> keine Eingabeüberprüfung
 
Code:
private void Meth (object value)
        {
            if (value is float || 
                value is int)
            {
                Console.WriteLine("Der übergebene Wert {0}", value);
            }

        }

damit ist es typsicher ;)
 
Zu 1.: Natürlich geht das! Wenn eine abgeleitete Klasse die gleichen Konstruktoren, wie die Basisklasse haben soll, musst du nur die Konstruktoren in der abgeleiteten Klasse anlegen und mit "base" den Basis-Konstruktor aufrufen.
Beispiel:
Code:
public class Mitarbeiter
{
    public Mitarbeiter()
    {
    }

    public Mitarbeiter(string name)
    {
    }

    public Mitarbeiter(string name, int lohn)
    {
    }
}

public class Vorarbeiter : Mitarbeiter
{
    public Vorarbeiter()
        : base()
    {
    }

    public Vorarbeiter(string name)
        : base(name)
    {
    }

    public Vorarbeiter(string name, int lohn)
        : base(name, lohn)
    {
    }
}

Zu 2.: Das Problem ist hier nur, dass der Compiler 40.42 implizit als double erkennt. (float und double unterscheiden sich ja nur in den Extremwerten (MinValue, MaxValue).) D. h. du musst dem Compiler mit 40.42f oder (float)40.42 sagen, dass das ein float-Wert ist.
Eine Methode mit object als Parametertyp halte ich für alles andere als typsicher.
 
Hi,

Danke für die Hilfe :)

1.Ich hatte oben ja noch das Problem, das man jedes einzelne Element einer Klasse mit einem Sichtbarkeitsspeziefer also (Protected, Public usw) versehen muss und nicht einen Public oder Protected bereich wie in C++ bestimmen kann. Gibt es dies in C# nicht?

Ich soll jetzt in einer Übung im Buch einen Stack programmieren also eine Klasse erstellen die die Funktionalität erfüllt, das man eine Funktion hat mit der man Objekte (es wird von einem beliebiegen Datum gesprochen?) auf einen virtuellen Stapel schieben kann. Dann soll es eine FUnktion geben die das letzte auf den Stapel verschobene Objekt zurück gibt. Dann einer mit dem man sich ausgeben lassen kann ob der Stuck lehr ist. Und dann eine Funktion um den Stapel zu lehren.

Ich habe zu dieser Aufgabe noch 2 Fragen:

2.Was ist in diesem Fall mit dem Datum gemeint? Handelt es sich um Klassen Instanzen, die ich inerhalb der Stack Klasse erstellen soll?

3.Wie kann ich diese Objekte löschen? Im Buch hab ich die Methode Finalize gefunden allerdings steht auch gleich dabei das diese FUnktion nur eingeschrenkt nutzbar ist..

Würde mich über Hilfe freuen :)

Gruß Abcd
 
zu 1. ich glaub solche bereiche wie in c++ gibts in c# nicht
zu 2. möglicherweise ist das Objekt das gespeichert werden soll ein Datum ist
zu 3. versuch mal Dispose()
 
Zurück
Oben