<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ro">
	<id>http://wiki.dcae.pub.ro/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Rhobincu</id>
	<title>WikiLabs - Contribuții utilizator [ro]</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.dcae.pub.ro/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Rhobincu"/>
	<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php/Special:Contribu%C8%9Bii/Rhobincu"/>
	<updated>2026-04-21T09:34:25Z</updated>
	<subtitle>Contribuții utilizator</subtitle>
	<generator>MediaWiki 1.35.14</generator>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_6&amp;diff=8330</id>
		<title>SDPT Lab 6</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_6&amp;diff=8330"/>
		<updated>2026-04-20T17:49:47Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Week 6 Lab Activity: CI/CD Pipelines &amp;amp; Custom Runners =&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
Today, we automate everything. You will transition from compiling code on your laptop to architecting a professional CI/CD pipeline. &lt;br /&gt;
&lt;br /&gt;
We will accomplish this in six phases:&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Repository Setup:&amp;#039;&amp;#039;&amp;#039; Migrating your code to GitLab.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Infrastructure:&amp;#039;&amp;#039;&amp;#039; Spinning up and registering your own local GitLab Runner via Docker.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Continuous Integration (Build):&amp;#039;&amp;#039;&amp;#039; Writing your first CI job and generating Artifacts.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Continuous Integration (Test):&amp;#039;&amp;#039;&amp;#039; Consuming Artifacts and testing via QEMU.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Continuous Deployment (CD):&amp;#039;&amp;#039;&amp;#039; Creating a simulated OTA firmware release restricted to the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; branch.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Cleanup:&amp;#039;&amp;#039;&amp;#039; Deregistering and destroying your local runner.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 1: Repository Setup ==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;1. Create a Project:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Log into GitLab and create a new blank project named &amp;lt;code&amp;gt;sdpt-smart-oven&amp;lt;/code&amp;gt;. Uncheck &amp;quot;Initialize repository with a README&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;2. Push Your Code:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Open your terminal on your laptop, navigate to your Week 5 project folder, and push your code to this new repository.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git init&lt;br /&gt;
git branch -m main&lt;br /&gt;
git remote add origin https://gitlab.cs.pub.ro/&amp;lt;your-username&amp;gt;/sdpt-smart-oven.git&lt;br /&gt;
git add .&lt;br /&gt;
git commit -m &amp;quot;Initial commit: Oven Controller with CMake and Docker&amp;quot;&lt;br /&gt;
git push -u origin main&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 2: Registering a Local Runner ==&lt;br /&gt;
GitLab provides shared runners, but embedded systems often require custom hardware or specific toolchains. We will host our own Runner!&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;1. Get Your Registration Token:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
In your GitLab project, go to &amp;#039;&amp;#039;&amp;#039;Settings&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;CI/CD&amp;#039;&amp;#039;&amp;#039;. Expand the &amp;#039;&amp;#039;&amp;#039;Runners&amp;#039;&amp;#039;&amp;#039; section. Under &amp;quot;Project runners&amp;quot;, click &amp;quot;New project runner&amp;quot;. Add the tag &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt; and click Create. Copy the &amp;#039;&amp;#039;&amp;#039;registration token&amp;#039;&amp;#039;&amp;#039; it gives you.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;2. Start the Runner via Docker:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
On your laptop terminal, run a background Docker container to act as your runner. (We mount the Docker socket so the runner can spawn its own containers!)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d --name my-local-runner --restart always -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;3. Register the Runner:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Now, execute the registration command inside the running container:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker exec -it my-local-runner gitlab-runner register&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;GitLab instance URL:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;https://gitlab.cs.pub.ro/&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Registration token:&amp;#039;&amp;#039;&amp;#039; (Paste your token from step 1)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Description:&amp;#039;&amp;#039;&amp;#039; My Laptop Runner&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Tags:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Executor:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Default image:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;ubuntu:22.04&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Refresh your GitLab Runners page. You should see a green circle indicating your local runner is alive and listening for jobs!&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 3: The Build Stage &amp;amp; Artifacts ==&lt;br /&gt;
We will now tell your Runner how to build our code. Create a file named exactly &amp;lt;code&amp;gt;.gitlab-ci.yml&amp;lt;/code&amp;gt; in your project root.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge (Part 1):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Image:&amp;#039;&amp;#039;&amp;#039; Set &amp;lt;code&amp;gt;image:&amp;lt;/code&amp;gt; to the ARM Docker image you built last week.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Stages:&amp;#039;&amp;#039;&amp;#039; Define three stages: &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;deploy&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;The Build Job:&amp;#039;&amp;#039;&amp;#039; Create a job named &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* Assign it to the &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; stage.&lt;br /&gt;
#* Use &amp;lt;code&amp;gt;tags: [local-embedded]&amp;lt;/code&amp;gt; to force this job to run on YOUR laptop&amp;#039;s runner.&lt;br /&gt;
#* In the &amp;lt;code&amp;gt;script&amp;lt;/code&amp;gt;, run CMake for &amp;lt;code&amp;gt;aarch64&amp;lt;/code&amp;gt; and run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* Create &amp;lt;code&amp;gt;artifacts&amp;lt;/code&amp;gt; to save the &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory (expire in 1 hour).&lt;br /&gt;
&lt;br /&gt;
Commit and push. Watch the pipeline in GitLab. Your laptop&amp;#039;s fan might spin up because *your* Docker daemon is doing the heavy lifting!&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 4: The Test Stage &amp;amp; Merge Checks ==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge (Part 2):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Add a job named &amp;lt;code&amp;gt;verify_logic&amp;lt;/code&amp;gt;:&lt;br /&gt;
# Stage: &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
# Tags: &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;dependencies:&amp;lt;/code&amp;gt; Require the artifacts from &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;lt;code&amp;gt;script:&amp;lt;/code&amp;gt; Navigate to &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; and execute tests using QEMU (&amp;lt;code&amp;gt;qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./unit_tests&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Test the Block:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Go to GitLab &amp;#039;&amp;#039;&amp;#039;Settings&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Merge Requests&amp;#039;&amp;#039;&amp;#039; -&amp;gt; Check &amp;quot;Pipelines must succeed&amp;quot;.&lt;br /&gt;
# Create a new branch: &amp;lt;code&amp;gt;git checkout -b feature/broken-math&amp;lt;/code&amp;gt;&lt;br /&gt;
# Break an assertion in your C++ tests and push the branch.&lt;br /&gt;
# Open a Merge Request. Watch the test stage fail and observe the Merge button physically lock you out! Fix the code, push again, and Merge it.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 5: Continuous Deployment (CD) ==&lt;br /&gt;
Once the code hits the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; branch, we want to handle two different types of deployments: an automated OTA release (Pull), and an on-demand Edge deployment (Push).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge (Part 3): Automated OTA Release&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Add a job named &amp;lt;code&amp;gt;release_ota_firmware&amp;lt;/code&amp;gt;:&lt;br /&gt;
# Stage: &amp;lt;code&amp;gt;deploy&amp;lt;/code&amp;gt;&lt;br /&gt;
# Tags: &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;dependencies:&amp;lt;/code&amp;gt; Pull from &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;lt;code&amp;gt;script:&amp;lt;/code&amp;gt; Rename your binary to a release format and simulate cryptographically signing it:&lt;br /&gt;
#* &amp;lt;code&amp;gt;mv build/unit_tests build/firmware_v1.bin&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;echo &amp;quot;CRYPTOGRAPHIC_SIGNATURE_OK&amp;quot; &amp;gt;&amp;gt; build/firmware_v1.bin&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Rules:&amp;#039;&amp;#039;&amp;#039; We ONLY want to release firmware automatically from the main branch! Add a &amp;lt;code&amp;gt;rules:&amp;lt;/code&amp;gt; section with &amp;lt;code&amp;gt;- if: &amp;#039;$CI_COMMIT_BRANCH == &amp;quot;main&amp;quot;&amp;#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Artifacts:&amp;#039;&amp;#039;&amp;#039; Save &amp;lt;code&amp;gt;build/firmware_v1.bin&amp;lt;/code&amp;gt; as an artifact that never expires.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge (Part 4): On-Demand Push Deployment&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Sometimes we need to instantly push an update to a specific machine (e.g., a prototype in the lab) without waiting for it to poll. We will simulate an SSH deployment using pipeline variables. &lt;br /&gt;
&lt;br /&gt;
Add another job named &amp;lt;code&amp;gt;deploy_to_edge_device&amp;lt;/code&amp;gt;:&lt;br /&gt;
# Stage: &amp;lt;code&amp;gt;deploy&amp;lt;/code&amp;gt;&lt;br /&gt;
# Tags: &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;dependencies:&amp;lt;/code&amp;gt; Pull from &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Rules:&amp;#039;&amp;#039;&amp;#039; We want this to be an &amp;quot;On-Demand&amp;quot; job that requires a human to click a play button. Add a &amp;lt;code&amp;gt;rules:&amp;lt;/code&amp;gt; section with &amp;lt;code&amp;gt;- when: manual&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;lt;code&amp;gt;script:&amp;lt;/code&amp;gt; Simulate securely pushing the binary to a specific IP address using an environment variable (&amp;lt;code&amp;gt;$TARGET_IP&amp;lt;/code&amp;gt;). Do not hardcode an IP here; we will inject it later!&lt;br /&gt;
#* &amp;lt;code&amp;gt;echo &amp;quot;Connecting to Edge Device at $TARGET_IP...&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;echo &amp;quot;scp build/unit_tests admin@$TARGET_IP:/opt/smart-oven/bin/&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;echo &amp;quot;Deployment to $TARGET_IP successful!&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Test the Deployments:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Push your code to &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt;. &lt;br /&gt;
# You will see the &amp;lt;code&amp;gt;release_ota_firmware&amp;lt;/code&amp;gt; job run automatically. &lt;br /&gt;
# The &amp;lt;code&amp;gt;deploy_to_edge_device&amp;lt;/code&amp;gt; job will be paused (marked with a &amp;quot;Play&amp;quot; icon). &lt;br /&gt;
# Click the Play icon. GitLab will take you to a new screen asking if you want to inject any environment variables.&lt;br /&gt;
# Add a variable with the Key &amp;lt;code&amp;gt;TARGET_IP&amp;lt;/code&amp;gt; and the Value &amp;lt;code&amp;gt;192.168.1.50&amp;lt;/code&amp;gt; (or any dummy IP address you prefer).&lt;br /&gt;
# Click &amp;quot;Run job&amp;quot; and check the terminal output to see your variable successfully injected into the simulated SSH command!&lt;br /&gt;
&lt;br /&gt;
== Phase 6: Cleanup ==&lt;br /&gt;
To prevent your runner from polling GitLab forever and draining your laptop battery, gracefully shut it down and remove it:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker stop my-local-runner&lt;br /&gt;
docker rm my-local-runner&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In the GitLab UI, go back to Settings -&amp;gt; CI/CD -&amp;gt; Runners, and delete the offline runner.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
=== Assignment Submission ===&lt;br /&gt;
Upload &amp;#039;&amp;#039;&amp;#039;ONLY&amp;#039;&amp;#039;&amp;#039; your finalized &amp;lt;code&amp;gt;.gitlab-ci.yml&amp;lt;/code&amp;gt; to the Moodle VPL assignment. The automated grading server will analyze your YAML syntax to ensure you correctly configured the stages, artifacts, custom runner routing, and deployment rules.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_6&amp;diff=8329</id>
		<title>SDPT Lab 6</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_6&amp;diff=8329"/>
		<updated>2026-04-19T17:27:43Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Phase 5: Continuous Deployment (CD) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Week 6 Lab Activity: CI/CD Pipelines &amp;amp; Custom Runners =&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
Today, we automate everything. You will transition from compiling code on your laptop to architecting a professional CI/CD pipeline. &lt;br /&gt;
&lt;br /&gt;
We will accomplish this in six phases:&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Repository Setup:&amp;#039;&amp;#039;&amp;#039; Migrating your code to GitLab.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Infrastructure:&amp;#039;&amp;#039;&amp;#039; Spinning up and registering your own local GitLab Runner via Docker.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Continuous Integration (Build):&amp;#039;&amp;#039;&amp;#039; Writing your first CI job and generating Artifacts.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Continuous Integration (Test):&amp;#039;&amp;#039;&amp;#039; Consuming Artifacts and testing via QEMU.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Continuous Deployment (CD):&amp;#039;&amp;#039;&amp;#039; Creating a simulated OTA firmware release restricted to the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; branch.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Cleanup:&amp;#039;&amp;#039;&amp;#039; Deregistering and destroying your local runner.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 1: Repository Setup ==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;1. Create a Project:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Log into GitLab and create a new blank project named &amp;lt;code&amp;gt;sdpt-smart-oven&amp;lt;/code&amp;gt;. Uncheck &amp;quot;Initialize repository with a README&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;2. Push Your Code:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Open your terminal on your laptop, navigate to your Week 5 project folder, and push your code to this new repository.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git init&lt;br /&gt;
git branch -m main&lt;br /&gt;
git remote add origin https://gitlab.com/&amp;lt;your-username&amp;gt;/sdpt-smart-oven.git&lt;br /&gt;
git add .&lt;br /&gt;
git commit -m &amp;quot;Initial commit: Oven Controller with CMake and Docker&amp;quot;&lt;br /&gt;
git push -u origin main&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 2: Registering a Local Runner ==&lt;br /&gt;
GitLab provides shared runners, but embedded systems often require custom hardware or specific toolchains. We will host our own Runner!&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;1. Get Your Registration Token:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
In your GitLab project, go to &amp;#039;&amp;#039;&amp;#039;Settings&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;CI/CD&amp;#039;&amp;#039;&amp;#039;. Expand the &amp;#039;&amp;#039;&amp;#039;Runners&amp;#039;&amp;#039;&amp;#039; section. Under &amp;quot;Project runners&amp;quot;, click &amp;quot;New project runner&amp;quot;. Add the tag &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt; and click Create. Copy the &amp;#039;&amp;#039;&amp;#039;registration token&amp;#039;&amp;#039;&amp;#039; it gives you.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;2. Start the Runner via Docker:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
On your laptop terminal, run a background Docker container to act as your runner. (We mount the Docker socket so the runner can spawn its own containers!)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d --name my-local-runner --restart always -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;3. Register the Runner:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Now, execute the registration command inside the running container:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker exec -it my-local-runner gitlab-runner register&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;GitLab instance URL:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;https://gitlab.com/&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Registration token:&amp;#039;&amp;#039;&amp;#039; (Paste your token from step 1)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Description:&amp;#039;&amp;#039;&amp;#039; My Laptop Runner&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Tags:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Executor:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Default image:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;ubuntu:22.04&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Refresh your GitLab Runners page. You should see a green circle indicating your local runner is alive and listening for jobs!&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 3: The Build Stage &amp;amp; Artifacts ==&lt;br /&gt;
We will now tell your Runner how to build our code. Create a file named exactly &amp;lt;code&amp;gt;.gitlab-ci.yml&amp;lt;/code&amp;gt; in your project root.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge (Part 1):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Image:&amp;#039;&amp;#039;&amp;#039; Set &amp;lt;code&amp;gt;image:&amp;lt;/code&amp;gt; to the ARM Docker image you built last week.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Stages:&amp;#039;&amp;#039;&amp;#039; Define three stages: &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;deploy&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;The Build Job:&amp;#039;&amp;#039;&amp;#039; Create a job named &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* Assign it to the &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; stage.&lt;br /&gt;
#* Use &amp;lt;code&amp;gt;tags: [local-embedded]&amp;lt;/code&amp;gt; to force this job to run on YOUR laptop&amp;#039;s runner.&lt;br /&gt;
#* In the &amp;lt;code&amp;gt;script&amp;lt;/code&amp;gt;, run CMake for &amp;lt;code&amp;gt;aarch64&amp;lt;/code&amp;gt; and run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* Create &amp;lt;code&amp;gt;artifacts&amp;lt;/code&amp;gt; to save the &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory (expire in 1 hour).&lt;br /&gt;
&lt;br /&gt;
Commit and push. Watch the pipeline in GitLab. Your laptop&amp;#039;s fan might spin up because *your* Docker daemon is doing the heavy lifting!&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 4: The Test Stage &amp;amp; Merge Checks ==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge (Part 2):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Add a job named &amp;lt;code&amp;gt;verify_logic&amp;lt;/code&amp;gt;:&lt;br /&gt;
# Stage: &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
# Tags: &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;dependencies:&amp;lt;/code&amp;gt; Require the artifacts from &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;lt;code&amp;gt;script:&amp;lt;/code&amp;gt; Navigate to &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; and execute tests using QEMU (&amp;lt;code&amp;gt;qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./unit_tests&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Test the Block:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Go to GitLab &amp;#039;&amp;#039;&amp;#039;Settings&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Merge Requests&amp;#039;&amp;#039;&amp;#039; -&amp;gt; Check &amp;quot;Pipelines must succeed&amp;quot;.&lt;br /&gt;
# Create a new branch: &amp;lt;code&amp;gt;git checkout -b feature/broken-math&amp;lt;/code&amp;gt;&lt;br /&gt;
# Break an assertion in your C++ tests and push the branch.&lt;br /&gt;
# Open a Merge Request. Watch the test stage fail and observe the Merge button physically lock you out! Fix the code, push again, and Merge it.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 5: Continuous Deployment (CD) ==&lt;br /&gt;
Once the code hits the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; branch, we want to handle two different types of deployments: an automated OTA release (Pull), and an on-demand Edge deployment (Push).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge (Part 3): Automated OTA Release&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Add a job named &amp;lt;code&amp;gt;release_ota_firmware&amp;lt;/code&amp;gt;:&lt;br /&gt;
# Stage: &amp;lt;code&amp;gt;deploy&amp;lt;/code&amp;gt;&lt;br /&gt;
# Tags: &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;dependencies:&amp;lt;/code&amp;gt; Pull from &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;lt;code&amp;gt;script:&amp;lt;/code&amp;gt; Rename your binary to a release format and simulate cryptographically signing it:&lt;br /&gt;
#* &amp;lt;code&amp;gt;mv build/unit_tests build/firmware_v1.bin&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;echo &amp;quot;CRYPTOGRAPHIC_SIGNATURE_OK&amp;quot; &amp;gt;&amp;gt; build/firmware_v1.bin&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Rules:&amp;#039;&amp;#039;&amp;#039; We ONLY want to release firmware automatically from the main branch! Add a &amp;lt;code&amp;gt;rules:&amp;lt;/code&amp;gt; section with &amp;lt;code&amp;gt;- if: &amp;#039;$CI_COMMIT_BRANCH == &amp;quot;main&amp;quot;&amp;#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Artifacts:&amp;#039;&amp;#039;&amp;#039; Save &amp;lt;code&amp;gt;build/firmware_v1.bin&amp;lt;/code&amp;gt; as an artifact that never expires.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge (Part 4): On-Demand Push Deployment&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Sometimes we need to instantly push an update to a specific machine (e.g., a prototype in the lab) without waiting for it to poll. We will simulate an SSH deployment using pipeline variables. &lt;br /&gt;
&lt;br /&gt;
Add another job named &amp;lt;code&amp;gt;deploy_to_edge_device&amp;lt;/code&amp;gt;:&lt;br /&gt;
# Stage: &amp;lt;code&amp;gt;deploy&amp;lt;/code&amp;gt;&lt;br /&gt;
# Tags: &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;dependencies:&amp;lt;/code&amp;gt; Pull from &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Rules:&amp;#039;&amp;#039;&amp;#039; We want this to be an &amp;quot;On-Demand&amp;quot; job that requires a human to click a play button. Add a &amp;lt;code&amp;gt;rules:&amp;lt;/code&amp;gt; section with &amp;lt;code&amp;gt;- when: manual&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;lt;code&amp;gt;script:&amp;lt;/code&amp;gt; Simulate securely pushing the binary to a specific IP address using an environment variable (&amp;lt;code&amp;gt;$TARGET_IP&amp;lt;/code&amp;gt;). Do not hardcode an IP here; we will inject it later!&lt;br /&gt;
#* &amp;lt;code&amp;gt;echo &amp;quot;Connecting to Edge Device at $TARGET_IP...&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;echo &amp;quot;scp build/unit_tests admin@$TARGET_IP:/opt/smart-oven/bin/&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;echo &amp;quot;Deployment to $TARGET_IP successful!&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Test the Deployments:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Push your code to &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt;. &lt;br /&gt;
# You will see the &amp;lt;code&amp;gt;release_ota_firmware&amp;lt;/code&amp;gt; job run automatically. &lt;br /&gt;
# The &amp;lt;code&amp;gt;deploy_to_edge_device&amp;lt;/code&amp;gt; job will be paused (marked with a &amp;quot;Play&amp;quot; icon). &lt;br /&gt;
# Click the Play icon. GitLab will take you to a new screen asking if you want to inject any environment variables.&lt;br /&gt;
# Add a variable with the Key &amp;lt;code&amp;gt;TARGET_IP&amp;lt;/code&amp;gt; and the Value &amp;lt;code&amp;gt;192.168.1.50&amp;lt;/code&amp;gt; (or any dummy IP address you prefer).&lt;br /&gt;
# Click &amp;quot;Run job&amp;quot; and check the terminal output to see your variable successfully injected into the simulated SSH command!&lt;br /&gt;
&lt;br /&gt;
== Phase 6: Cleanup ==&lt;br /&gt;
To prevent your runner from polling GitLab forever and draining your laptop battery, gracefully shut it down and remove it:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker stop my-local-runner&lt;br /&gt;
docker rm my-local-runner&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In the GitLab UI, go back to Settings -&amp;gt; CI/CD -&amp;gt; Runners, and delete the offline runner.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
=== Assignment Submission ===&lt;br /&gt;
Upload &amp;#039;&amp;#039;&amp;#039;ONLY&amp;#039;&amp;#039;&amp;#039; your finalized &amp;lt;code&amp;gt;.gitlab-ci.yml&amp;lt;/code&amp;gt; to the Moodle VPL assignment. The automated grading server will analyze your YAML syntax to ensure you correctly configured the stages, artifacts, custom runner routing, and deployment rules.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_6&amp;diff=8328</id>
		<title>SDPT Lab 6</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_6&amp;diff=8328"/>
		<updated>2026-04-19T17:08:20Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Phase 5: Continuous Deployment (CD) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Week 6 Lab Activity: CI/CD Pipelines &amp;amp; Custom Runners =&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
Today, we automate everything. You will transition from compiling code on your laptop to architecting a professional CI/CD pipeline. &lt;br /&gt;
&lt;br /&gt;
We will accomplish this in six phases:&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Repository Setup:&amp;#039;&amp;#039;&amp;#039; Migrating your code to GitLab.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Infrastructure:&amp;#039;&amp;#039;&amp;#039; Spinning up and registering your own local GitLab Runner via Docker.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Continuous Integration (Build):&amp;#039;&amp;#039;&amp;#039; Writing your first CI job and generating Artifacts.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Continuous Integration (Test):&amp;#039;&amp;#039;&amp;#039; Consuming Artifacts and testing via QEMU.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Continuous Deployment (CD):&amp;#039;&amp;#039;&amp;#039; Creating a simulated OTA firmware release restricted to the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; branch.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Cleanup:&amp;#039;&amp;#039;&amp;#039; Deregistering and destroying your local runner.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 1: Repository Setup ==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;1. Create a Project:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Log into GitLab and create a new blank project named &amp;lt;code&amp;gt;sdpt-smart-oven&amp;lt;/code&amp;gt;. Uncheck &amp;quot;Initialize repository with a README&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;2. Push Your Code:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Open your terminal on your laptop, navigate to your Week 5 project folder, and push your code to this new repository.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git init&lt;br /&gt;
git branch -m main&lt;br /&gt;
git remote add origin https://gitlab.com/&amp;lt;your-username&amp;gt;/sdpt-smart-oven.git&lt;br /&gt;
git add .&lt;br /&gt;
git commit -m &amp;quot;Initial commit: Oven Controller with CMake and Docker&amp;quot;&lt;br /&gt;
git push -u origin main&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 2: Registering a Local Runner ==&lt;br /&gt;
GitLab provides shared runners, but embedded systems often require custom hardware or specific toolchains. We will host our own Runner!&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;1. Get Your Registration Token:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
In your GitLab project, go to &amp;#039;&amp;#039;&amp;#039;Settings&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;CI/CD&amp;#039;&amp;#039;&amp;#039;. Expand the &amp;#039;&amp;#039;&amp;#039;Runners&amp;#039;&amp;#039;&amp;#039; section. Under &amp;quot;Project runners&amp;quot;, click &amp;quot;New project runner&amp;quot;. Add the tag &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt; and click Create. Copy the &amp;#039;&amp;#039;&amp;#039;registration token&amp;#039;&amp;#039;&amp;#039; it gives you.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;2. Start the Runner via Docker:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
On your laptop terminal, run a background Docker container to act as your runner. (We mount the Docker socket so the runner can spawn its own containers!)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d --name my-local-runner --restart always -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;3. Register the Runner:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Now, execute the registration command inside the running container:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker exec -it my-local-runner gitlab-runner register&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;GitLab instance URL:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;https://gitlab.com/&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Registration token:&amp;#039;&amp;#039;&amp;#039; (Paste your token from step 1)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Description:&amp;#039;&amp;#039;&amp;#039; My Laptop Runner&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Tags:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Executor:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Default image:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;ubuntu:22.04&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Refresh your GitLab Runners page. You should see a green circle indicating your local runner is alive and listening for jobs!&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 3: The Build Stage &amp;amp; Artifacts ==&lt;br /&gt;
We will now tell your Runner how to build our code. Create a file named exactly &amp;lt;code&amp;gt;.gitlab-ci.yml&amp;lt;/code&amp;gt; in your project root.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge (Part 1):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Image:&amp;#039;&amp;#039;&amp;#039; Set &amp;lt;code&amp;gt;image:&amp;lt;/code&amp;gt; to the ARM Docker image you built last week.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Stages:&amp;#039;&amp;#039;&amp;#039; Define three stages: &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;deploy&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;The Build Job:&amp;#039;&amp;#039;&amp;#039; Create a job named &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* Assign it to the &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; stage.&lt;br /&gt;
#* Use &amp;lt;code&amp;gt;tags: [local-embedded]&amp;lt;/code&amp;gt; to force this job to run on YOUR laptop&amp;#039;s runner.&lt;br /&gt;
#* In the &amp;lt;code&amp;gt;script&amp;lt;/code&amp;gt;, run CMake for &amp;lt;code&amp;gt;aarch64&amp;lt;/code&amp;gt; and run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* Create &amp;lt;code&amp;gt;artifacts&amp;lt;/code&amp;gt; to save the &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory (expire in 1 hour).&lt;br /&gt;
&lt;br /&gt;
Commit and push. Watch the pipeline in GitLab. Your laptop&amp;#039;s fan might spin up because *your* Docker daemon is doing the heavy lifting!&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 4: The Test Stage &amp;amp; Merge Checks ==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge (Part 2):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Add a job named &amp;lt;code&amp;gt;verify_logic&amp;lt;/code&amp;gt;:&lt;br /&gt;
# Stage: &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
# Tags: &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;dependencies:&amp;lt;/code&amp;gt; Require the artifacts from &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;lt;code&amp;gt;script:&amp;lt;/code&amp;gt; Navigate to &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; and execute tests using QEMU (&amp;lt;code&amp;gt;qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./unit_tests&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Test the Block:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Go to GitLab &amp;#039;&amp;#039;&amp;#039;Settings&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Merge Requests&amp;#039;&amp;#039;&amp;#039; -&amp;gt; Check &amp;quot;Pipelines must succeed&amp;quot;.&lt;br /&gt;
# Create a new branch: &amp;lt;code&amp;gt;git checkout -b feature/broken-math&amp;lt;/code&amp;gt;&lt;br /&gt;
# Break an assertion in your C++ tests and push the branch.&lt;br /&gt;
# Open a Merge Request. Watch the test stage fail and observe the Merge button physically lock you out! Fix the code, push again, and Merge it.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 5: Continuous Deployment (CD) ==&lt;br /&gt;
Once the code hits the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; branch, we want to handle two different types of deployments: an automated OTA release (Pull), and an on-demand Edge deployment (Push).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge (Part 3): Automated OTA Release&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Add a job named &amp;lt;code&amp;gt;release_ota_firmware&amp;lt;/code&amp;gt;:&lt;br /&gt;
# Stage: &amp;lt;code&amp;gt;deploy&amp;lt;/code&amp;gt;&lt;br /&gt;
# Tags: &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;dependencies:&amp;lt;/code&amp;gt; Pull from &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;lt;code&amp;gt;script:&amp;lt;/code&amp;gt; Rename your binary to a release format and simulate cryptographically signing it:&lt;br /&gt;
#* &amp;lt;code&amp;gt;mv build/unit_tests build/firmware_v1.bin&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;echo &amp;quot;CRYPTOGRAPHIC_SIGNATURE_OK&amp;quot; &amp;gt;&amp;gt; build/firmware_v1.bin&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Rules:&amp;#039;&amp;#039;&amp;#039; We ONLY want to release firmware automatically from the main branch! Add a &amp;lt;code&amp;gt;rules:&amp;lt;/code&amp;gt; section with &amp;lt;code&amp;gt;- if: &amp;#039;$CI_COMMIT_BRANCH == &amp;quot;main&amp;quot;&amp;#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Artifacts:&amp;#039;&amp;#039;&amp;#039; Save &amp;lt;code&amp;gt;build/firmware_v1.bin&amp;lt;/code&amp;gt; as an artifact that never expires.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge (Part 4): On-Demand Push Deployment&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Sometimes we need to instantly push an update to a specific machine (e.g., a prototype in the lab) without waiting for it to poll. We will simulate an SSH deployment using pipeline variables. &lt;br /&gt;
&lt;br /&gt;
Add another job named &amp;lt;code&amp;gt;deploy_to_edge_device&amp;lt;/code&amp;gt;:&lt;br /&gt;
# Stage: &amp;lt;code&amp;gt;deploy&amp;lt;/code&amp;gt;&lt;br /&gt;
# Tags: &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;dependencies:&amp;lt;/code&amp;gt; Pull from &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Rules:&amp;#039;&amp;#039;&amp;#039; We want this to be an &amp;quot;On-Demand&amp;quot; job that requires a human to click a play button. Add a &amp;lt;code&amp;gt;rules:&amp;lt;/code&amp;gt; section with &amp;lt;code&amp;gt;- when: manual&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;lt;code&amp;gt;script:&amp;lt;/code&amp;gt; Simulate securely pushing the binary to a specific IP address using an environment variable (&amp;lt;code&amp;gt;$TARGET_IP&amp;lt;/code&amp;gt;):&lt;br /&gt;
#* &amp;lt;code&amp;gt;echo &amp;quot;Connecting to Edge Device at $TARGET_IP...&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;echo &amp;quot;scp build/unit_tests admin@$TARGET_IP:/opt/smart-oven/bin/&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;echo &amp;quot;Deployment to $TARGET_IP successful!&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Test the Deployments:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Push your code to &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt;. &lt;br /&gt;
# You will see the &amp;lt;code&amp;gt;release_ota_firmware&amp;lt;/code&amp;gt; job run automatically. &lt;br /&gt;
# The &amp;lt;code&amp;gt;deploy_to_edge_device&amp;lt;/code&amp;gt; job will be paused (marked with a &amp;quot;Play&amp;quot; icon). &lt;br /&gt;
# Click the Play icon, and GitLab will allow you to manually input a value for &amp;lt;code&amp;gt;TARGET_IP&amp;lt;/code&amp;gt; before executing the push!&lt;br /&gt;
&lt;br /&gt;
== Phase 6: Cleanup ==&lt;br /&gt;
To prevent your runner from polling GitLab forever and draining your laptop battery, gracefully shut it down and remove it:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker stop my-local-runner&lt;br /&gt;
docker rm my-local-runner&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In the GitLab UI, go back to Settings -&amp;gt; CI/CD -&amp;gt; Runners, and delete the offline runner.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
=== Assignment Submission ===&lt;br /&gt;
Upload &amp;#039;&amp;#039;&amp;#039;ONLY&amp;#039;&amp;#039;&amp;#039; your finalized &amp;lt;code&amp;gt;.gitlab-ci.yml&amp;lt;/code&amp;gt; to the Moodle VPL assignment. The automated grading server will analyze your YAML syntax to ensure you correctly configured the stages, artifacts, custom runner routing, and deployment rules.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_6&amp;diff=8327</id>
		<title>SDPT Lab 6</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_6&amp;diff=8327"/>
		<updated>2026-04-19T17:05:52Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Week 6 Lab Activity: CI/CD Pipelines &amp;amp; Custom Runners =&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
Today, we automate everything. You will transition from compiling code on your laptop to architecting a professional CI/CD pipeline. &lt;br /&gt;
&lt;br /&gt;
We will accomplish this in six phases:&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Repository Setup:&amp;#039;&amp;#039;&amp;#039; Migrating your code to GitLab.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Infrastructure:&amp;#039;&amp;#039;&amp;#039; Spinning up and registering your own local GitLab Runner via Docker.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Continuous Integration (Build):&amp;#039;&amp;#039;&amp;#039; Writing your first CI job and generating Artifacts.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Continuous Integration (Test):&amp;#039;&amp;#039;&amp;#039; Consuming Artifacts and testing via QEMU.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Continuous Deployment (CD):&amp;#039;&amp;#039;&amp;#039; Creating a simulated OTA firmware release restricted to the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; branch.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Cleanup:&amp;#039;&amp;#039;&amp;#039; Deregistering and destroying your local runner.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 1: Repository Setup ==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;1. Create a Project:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Log into GitLab and create a new blank project named &amp;lt;code&amp;gt;sdpt-smart-oven&amp;lt;/code&amp;gt;. Uncheck &amp;quot;Initialize repository with a README&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;2. Push Your Code:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Open your terminal on your laptop, navigate to your Week 5 project folder, and push your code to this new repository.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git init&lt;br /&gt;
git branch -m main&lt;br /&gt;
git remote add origin https://gitlab.com/&amp;lt;your-username&amp;gt;/sdpt-smart-oven.git&lt;br /&gt;
git add .&lt;br /&gt;
git commit -m &amp;quot;Initial commit: Oven Controller with CMake and Docker&amp;quot;&lt;br /&gt;
git push -u origin main&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 2: Registering a Local Runner ==&lt;br /&gt;
GitLab provides shared runners, but embedded systems often require custom hardware or specific toolchains. We will host our own Runner!&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;1. Get Your Registration Token:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
In your GitLab project, go to &amp;#039;&amp;#039;&amp;#039;Settings&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;CI/CD&amp;#039;&amp;#039;&amp;#039;. Expand the &amp;#039;&amp;#039;&amp;#039;Runners&amp;#039;&amp;#039;&amp;#039; section. Under &amp;quot;Project runners&amp;quot;, click &amp;quot;New project runner&amp;quot;. Add the tag &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt; and click Create. Copy the &amp;#039;&amp;#039;&amp;#039;registration token&amp;#039;&amp;#039;&amp;#039; it gives you.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;2. Start the Runner via Docker:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
On your laptop terminal, run a background Docker container to act as your runner. (We mount the Docker socket so the runner can spawn its own containers!)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -d --name my-local-runner --restart always -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;3. Register the Runner:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Now, execute the registration command inside the running container:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker exec -it my-local-runner gitlab-runner register&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;GitLab instance URL:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;https://gitlab.com/&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Registration token:&amp;#039;&amp;#039;&amp;#039; (Paste your token from step 1)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Description:&amp;#039;&amp;#039;&amp;#039; My Laptop Runner&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Tags:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Executor:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;docker&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Default image:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;ubuntu:22.04&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Refresh your GitLab Runners page. You should see a green circle indicating your local runner is alive and listening for jobs!&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 3: The Build Stage &amp;amp; Artifacts ==&lt;br /&gt;
We will now tell your Runner how to build our code. Create a file named exactly &amp;lt;code&amp;gt;.gitlab-ci.yml&amp;lt;/code&amp;gt; in your project root.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge (Part 1):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Image:&amp;#039;&amp;#039;&amp;#039; Set &amp;lt;code&amp;gt;image:&amp;lt;/code&amp;gt; to the ARM Docker image you built last week.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Stages:&amp;#039;&amp;#039;&amp;#039; Define three stages: &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;deploy&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;The Build Job:&amp;#039;&amp;#039;&amp;#039; Create a job named &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* Assign it to the &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; stage.&lt;br /&gt;
#* Use &amp;lt;code&amp;gt;tags: [local-embedded]&amp;lt;/code&amp;gt; to force this job to run on YOUR laptop&amp;#039;s runner.&lt;br /&gt;
#* In the &amp;lt;code&amp;gt;script&amp;lt;/code&amp;gt;, run CMake for &amp;lt;code&amp;gt;aarch64&amp;lt;/code&amp;gt; and run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* Create &amp;lt;code&amp;gt;artifacts&amp;lt;/code&amp;gt; to save the &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory (expire in 1 hour).&lt;br /&gt;
&lt;br /&gt;
Commit and push. Watch the pipeline in GitLab. Your laptop&amp;#039;s fan might spin up because *your* Docker daemon is doing the heavy lifting!&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 4: The Test Stage &amp;amp; Merge Checks ==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge (Part 2):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Add a job named &amp;lt;code&amp;gt;verify_logic&amp;lt;/code&amp;gt;:&lt;br /&gt;
# Stage: &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
# Tags: &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;dependencies:&amp;lt;/code&amp;gt; Require the artifacts from &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;lt;code&amp;gt;script:&amp;lt;/code&amp;gt; Navigate to &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; and execute tests using QEMU (&amp;lt;code&amp;gt;qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./unit_tests&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Test the Block:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Go to GitLab &amp;#039;&amp;#039;&amp;#039;Settings&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Merge Requests&amp;#039;&amp;#039;&amp;#039; -&amp;gt; Check &amp;quot;Pipelines must succeed&amp;quot;.&lt;br /&gt;
# Create a new branch: &amp;lt;code&amp;gt;git checkout -b feature/broken-math&amp;lt;/code&amp;gt;&lt;br /&gt;
# Break an assertion in your C++ tests and push the branch.&lt;br /&gt;
# Open a Merge Request. Watch the test stage fail and observe the Merge button physically lock you out! Fix the code, push again, and Merge it.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 5: Continuous Deployment (CD) ==&lt;br /&gt;
Once the code hits the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; branch, we want to automatically package it for an Over-The-Air (OTA) firmware update.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge (Part 3):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Add a final job named &amp;lt;code&amp;gt;release_ota_firmware&amp;lt;/code&amp;gt;:&lt;br /&gt;
# Stage: &amp;lt;code&amp;gt;deploy&amp;lt;/code&amp;gt;&lt;br /&gt;
# Tags: &amp;lt;code&amp;gt;local-embedded&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;dependencies:&amp;lt;/code&amp;gt; Pull from &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;lt;code&amp;gt;script:&amp;lt;/code&amp;gt; Rename your binary to a release format and simulate cryptographically signing it:&lt;br /&gt;
#* &amp;lt;code&amp;gt;mv build/unit_tests build/firmware_v1.bin&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;echo &amp;quot;CRYPTOGRAPHIC_SIGNATURE_OK&amp;quot; &amp;gt;&amp;gt; build/firmware_v1.bin&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Rules:&amp;#039;&amp;#039;&amp;#039; We ONLY want to release firmware from the main branch! Add a &amp;lt;code&amp;gt;rules:&amp;lt;/code&amp;gt; section with &amp;lt;code&amp;gt;- if: &amp;#039;$CI_COMMIT_BRANCH == &amp;quot;main&amp;quot;&amp;#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Artifacts:&amp;#039;&amp;#039;&amp;#039; Save &amp;lt;code&amp;gt;build/firmware_v1.bin&amp;lt;/code&amp;gt; as an artifact that never expires.&lt;br /&gt;
&lt;br /&gt;
Push to main. You should see a 3-stage pipeline complete successfully. You can now download your final &amp;quot;signed&amp;quot; firmware directly from the GitLab UI!&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 6: Cleanup ==&lt;br /&gt;
To prevent your runner from polling GitLab forever and draining your laptop battery, gracefully shut it down and remove it:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker stop my-local-runner&lt;br /&gt;
docker rm my-local-runner&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In the GitLab UI, go back to Settings -&amp;gt; CI/CD -&amp;gt; Runners, and delete the offline runner.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
=== Assignment Submission ===&lt;br /&gt;
Upload &amp;#039;&amp;#039;&amp;#039;ONLY&amp;#039;&amp;#039;&amp;#039; your finalized &amp;lt;code&amp;gt;.gitlab-ci.yml&amp;lt;/code&amp;gt; to the Moodle VPL assignment. The automated grading server will analyze your YAML syntax to ensure you correctly configured the stages, artifacts, custom runner routing, and deployment rules.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_6&amp;diff=8326</id>
		<title>SDPT Lab 6</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_6&amp;diff=8326"/>
		<updated>2026-04-19T17:03:02Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: Pagină nouă: = Week 6 Lab Activity: Continuous Integration (CI) with GitLab =  == Objective == Today, we automate everything. You will transition from compiling code on your laptop to architect...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Week 6 Lab Activity: Continuous Integration (CI) with GitLab =&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
Today, we automate everything. You will transition from compiling code on your laptop to architecting a professional CI pipeline. You will use your Docker image from last week to cross-compile your C++ code, run your Google Tests in QEMU, and configure GitLab to mechanically prevent broken code from ever reaching the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; branch.&lt;br /&gt;
&lt;br /&gt;
We will accomplish this in four phases:&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Repository Setup:&amp;#039;&amp;#039;&amp;#039; Migrating your code to GitLab.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;The Build Stage:&amp;#039;&amp;#039;&amp;#039; Writing your first CI job and generating Artifacts.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;The Test Stage:&amp;#039;&amp;#039;&amp;#039; Consuming Artifacts and failing the pipeline on bad tests.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Merge Checks:&amp;#039;&amp;#039;&amp;#039; Enforcing quality control via Merge Requests.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 1: Repository Setup ==&lt;br /&gt;
To use GitLab CI, your code must live on a GitLab server.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;1. Create a Project:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Log into GitLab and create a new blank project named &amp;lt;code&amp;gt;sdpt-smart-oven&amp;lt;/code&amp;gt;. Uncheck &amp;quot;Initialize repository with a README&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;2. Push Your Code:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Open your terminal on your laptop, navigate to your Week 5 project folder, and push your code to this new repository.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git init&lt;br /&gt;
git branch -m main&lt;br /&gt;
git remote add origin https://gitlab.com/&amp;lt;your-username&amp;gt;/sdpt-smart-oven.git&lt;br /&gt;
git add .&lt;br /&gt;
git commit -m &amp;quot;Initial commit: Oven Controller with CMake and Docker&amp;quot;&lt;br /&gt;
git push -u origin main&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 2: The Build Stage &amp;amp; Artifacts ==&lt;br /&gt;
We will now tell the GitLab Runner how to build our code using the Docker image you designed last week.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Create a file named exactly &amp;lt;code&amp;gt;.gitlab-ci.yml&amp;lt;/code&amp;gt; in the root of your project. Write the YAML to meet these specifications:&lt;br /&gt;
&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Image:&amp;#039;&amp;#039;&amp;#039; Set the global &amp;lt;code&amp;gt;image:&amp;lt;/code&amp;gt; to the Docker registry URL of the ARM image you built in Week 5 (or use a public equivalent provided by the instructor, e.g., &amp;lt;code&amp;gt;registry.gitlab.com/sdpt-course/arm-build-env:latest&amp;lt;/code&amp;gt;).&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Stages:&amp;#039;&amp;#039;&amp;#039; Define two stages: &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;The Build Job:&amp;#039;&amp;#039;&amp;#039; Create a job named &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* Assign it to the &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; stage.&lt;br /&gt;
#* In the &amp;lt;code&amp;gt;script&amp;lt;/code&amp;gt; section, create a build folder, run CMake for the &amp;lt;code&amp;gt;aarch64&amp;lt;/code&amp;gt; compiler, and run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Artifacts:&amp;#039;&amp;#039;&amp;#039; Tell GitLab to save the &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory as an artifact that expires in 1 hour. (If you forget this, your compiled binary will be deleted before the test stage starts!)&lt;br /&gt;
&lt;br /&gt;
Commit and push this file. Go to your GitLab project -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Build&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Pipelines&amp;#039;&amp;#039;&amp;#039;. You should see your pipeline running! Click on it to watch the live terminal output of the GitLab Runner.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 3: The Test Stage ==&lt;br /&gt;
Once your build job turns green, it&amp;#039;s time to test the artifact.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Update your YAML:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Add a second job named &amp;lt;code&amp;gt;verify_logic&amp;lt;/code&amp;gt; to your &amp;lt;code&amp;gt;.gitlab-ci.yml&amp;lt;/code&amp;gt;:&lt;br /&gt;
# Assign it to the &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt; stage.&lt;br /&gt;
# Use the &amp;lt;code&amp;gt;dependencies:&amp;lt;/code&amp;gt; keyword to explicitly require the artifacts from &amp;lt;code&amp;gt;compile_firmware&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the &amp;lt;code&amp;gt;script&amp;lt;/code&amp;gt; section, navigate to the &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory and execute your tests using QEMU (&amp;lt;code&amp;gt;qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./unit_tests&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Push the updated YAML. Watch the pipeline. The Runner will download the compiled binary from the previous stage and execute your tests!&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 4: Merge Checks and Failure (The DevOps Climax) ==&lt;br /&gt;
A pipeline is useless if developers can just bypass it. We will now configure GitLab to block bad code.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;1. Protect the Main Branch:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
In GitLab, go to &amp;#039;&amp;#039;&amp;#039;Settings&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Merge Requests&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
Scroll down to &amp;#039;&amp;#039;&amp;#039;Merge checks&amp;#039;&amp;#039;&amp;#039; and check the box that says: &amp;#039;&amp;#039;&amp;quot;Pipelines must succeed&amp;quot;&amp;#039;&amp;#039;. Save changes.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;2. Create a Feature Branch:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Back on your laptop terminal, create a new branch:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git checkout -b feature/broken-sensor&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;3. Sabotage the Code!&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Open your &amp;lt;code&amp;gt;test_oven.cpp&amp;lt;/code&amp;gt; file. Intentionally change a mathematical assertion so that it will fail (e.g., change &amp;lt;code&amp;gt;EXPECT_EQ(temp, 100);&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;EXPECT_EQ(temp, 999);&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;4. Push and Open a Merge Request:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Commit your broken test and push the branch to GitLab. &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git commit -am &amp;quot;feat: updated sensor logic (with bugs)&amp;quot;&lt;br /&gt;
git push -u origin feature/broken-sensor&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In GitLab, open a &amp;#039;&amp;#039;&amp;#039;Merge Request&amp;#039;&amp;#039;&amp;#039; from your feature branch into &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;5. Observe the Block:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Wait for the pipeline to run. The Build stage will pass, but the Test stage will turn RED because Google Test caught your broken math. &lt;br /&gt;
Look at the Merge Request page. &amp;#039;&amp;#039;&amp;#039;The Merge button is physically disabled!&amp;#039;&amp;#039;&amp;#039; GitLab has successfully protected your production code from human error.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;6. Fix and Merge:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Fix the test on your laptop, commit, and push again. The pipeline will automatically re-run, turn green, and unlock the Merge button. Click Merge!&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
=== Assignment Submission ===&lt;br /&gt;
Upload &amp;#039;&amp;#039;&amp;#039;ONLY&amp;#039;&amp;#039;&amp;#039; your finalized &amp;lt;code&amp;gt;.gitlab-ci.yml&amp;lt;/code&amp;gt; to the Moodle VPL assignment. The automated grading server will analyze your YAML syntax to ensure you correctly configured the stages, artifacts, and QEMU execution.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=Software_Development_Process_and_Testing&amp;diff=8325</id>
		<title>Software Development Process and Testing</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=Software_Development_Process_and_Testing&amp;diff=8325"/>
		<updated>2026-04-19T17:02:55Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[SDPT Lab 1]]&lt;br /&gt;
* [[SDPT Lab 2]]&lt;br /&gt;
* [[SDPT Lab 3]]&lt;br /&gt;
* [[SDPT Lab 4]]&lt;br /&gt;
* [[SDPT Lab 5]]&lt;br /&gt;
* [[SDPT Lab 6]]&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_5&amp;diff=8317</id>
		<title>SDPT Lab 5</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_5&amp;diff=8317"/>
		<updated>2026-03-30T13:55:46Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Week 5 Lab Activity: Containerization &amp;amp; Cross-Compilation =&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
This week, we eliminate the &amp;quot;It works on my machine&amp;quot; problem. You will learn how to build isolated Linux environments, cross-compile your &amp;lt;code&amp;gt;OvenController&amp;lt;/code&amp;gt; C++ code for an ARM architecture, and solve the complex problem of linking third-party static and dynamic libraries compiled for foreign architectures.&lt;br /&gt;
&lt;br /&gt;
We will accomplish this in three phases:&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Preparing CMake:&amp;#039;&amp;#039;&amp;#039; Updating the build system to link an external database library.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;The Manual Container (The &amp;quot;Old Way&amp;quot;):&amp;#039;&amp;#039;&amp;#039; Building the cross-compilation environment by hand to understand the underlying mechanics.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Infrastructure as Code (The &amp;quot;Modern Way&amp;quot;):&amp;#039;&amp;#039;&amp;#039; Automating the entire environment with a &amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 1: Preparing CMake for Foreign Libraries ==&lt;br /&gt;
Imagine our &amp;lt;code&amp;gt;OvenController&amp;lt;/code&amp;gt; needs to log telemetry data locally using an SQLite database. To do this, we need to link the &amp;lt;code&amp;gt;sqlite3&amp;lt;/code&amp;gt; library. &lt;br /&gt;
&lt;br /&gt;
Open your &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt; from Week 4 and add the standard linking commands. &amp;#039;&amp;#039;(Note: CMake is smart enough to look for the correct architecture version of this library based on the compiler we provide later).&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cmake&amp;quot;&amp;gt;&lt;br /&gt;
# Add this near the bottom of your CMakeLists.txt&lt;br /&gt;
find_package(PkgConfig REQUIRED)&lt;br /&gt;
pkg_check_modules(SQLITE3 REQUIRED sqlite3)&lt;br /&gt;
&lt;br /&gt;
# Add the includes and link the library to your executable&lt;br /&gt;
target_include_directories(unit_tests PRIVATE ${SQLITE3_INCLUDE_DIRS})&lt;br /&gt;
target_link_libraries(unit_tests PRIVATE ${SQLITE3_LIBRARIES})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 2: The Manual Container (The &amp;quot;Old Way&amp;quot;) ==&lt;br /&gt;
Before we automate, let&amp;#039;s understand what Docker is actually doing under the hood.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;1. Start a raw, interactive Ubuntu container:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Open your terminal and run a fresh Ubuntu 22.04 image, mounting your current code directory into &amp;lt;code&amp;gt;/app&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -it --name manual-build-env -v ${PWD}:/app ubuntu:22.04 /bin/bash&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Notice your terminal prompt has changed. You are now the root user inside an isolated Linux environment.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;2. The &amp;quot;Multiarch&amp;quot; Superpower:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
If we just run &amp;lt;code&amp;gt;apt-get install libsqlite3-dev&amp;lt;/code&amp;gt;, Ubuntu will download the &amp;lt;code&amp;gt;x86_64&amp;lt;/code&amp;gt; version. If we try to cross-compile our ARM code against it, the linker will violently crash. We must explicitly tell Ubuntu&amp;#039;s package manager to accept packages for a foreign architecture (&amp;lt;code&amp;gt;arm64&amp;lt;/code&amp;gt;).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dpkg --add-architecture arm64&lt;br /&gt;
apt-get update&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;3. Install the Toolchain and Foreign Libraries:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Now we install our cross-compiler, QEMU emulator, and the specifically compiled &amp;#039;&amp;#039;&amp;#039;ARM version&amp;#039;&amp;#039;&amp;#039; of our library (&amp;lt;code&amp;gt;:arm64&amp;lt;/code&amp;gt;).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt-get install -y build-essential cmake pkg-config g++-aarch64-linux-gnu qemu-user qemu-user-static&lt;br /&gt;
apt-get install -y libsqlite3-dev:arm64&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;4. Cross-Compile and Emulate:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Navigate to your mounted code and build the project for ARM. We use a command-line flag to tell CMake to use the ARM compiler instead of native GCC.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /app&lt;br /&gt;
mkdir build_arm &amp;amp;&amp;amp; cd build_arm&lt;br /&gt;
cmake -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ ..&lt;br /&gt;
make&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you try to run &amp;lt;code&amp;gt;./unit_tests&amp;lt;/code&amp;gt; natively, Linux will throw an &amp;lt;code&amp;gt;Exec format error&amp;lt;/code&amp;gt;. Use QEMU to emulate the execution of your ARM binary. Because we linked a dynamic library, we must tell QEMU where to find the ARM shared objects (&amp;lt;code&amp;gt;-L&amp;lt;/code&amp;gt; flag):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./unit_tests&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Verify that your Google Tests pass on the emulated architecture!&amp;#039;&amp;#039; Type &amp;lt;code&amp;gt;exit&amp;lt;/code&amp;gt; to leave and stop the container.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 3: Infrastructure as Code (The &amp;quot;Modern Way&amp;quot;) ==&lt;br /&gt;
Manually typing &amp;lt;code&amp;gt;apt-get&amp;lt;/code&amp;gt; commands, enabling architectures, and committing containers is tedious and error-prone. Modern DevOps engineers automate this using a &amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Challenge:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Create a file named exactly &amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt; (no extension) in your project root. Translate the manual steps you just took into an automated recipe that meets the following strict specifications:&lt;br /&gt;
&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Base Image:&amp;#039;&amp;#039;&amp;#039; Must use &amp;lt;code&amp;gt;ubuntu:22.04&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Environment:&amp;#039;&amp;#039;&amp;#039; Set &amp;lt;code&amp;gt;DEBIAN_FRONTEND&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;noninteractive&amp;lt;/code&amp;gt; to prevent the build from hanging on timezone prompts.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Architecture:&amp;#039;&amp;#039;&amp;#039; Use a &amp;lt;code&amp;gt;RUN&amp;lt;/code&amp;gt; command to add the &amp;lt;code&amp;gt;arm64&amp;lt;/code&amp;gt; architecture to &amp;lt;code&amp;gt;dpkg&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;The Mega-Layer:&amp;#039;&amp;#039;&amp;#039; Use a single &amp;lt;code&amp;gt;RUN&amp;lt;/code&amp;gt; command to update &amp;lt;code&amp;gt;apt-get&amp;lt;/code&amp;gt;, install all required tools (&amp;lt;code&amp;gt;build-essential cmake pkg-config g++-aarch64-linux-gnu qemu-user qemu-user-static libsqlite3-dev:arm64&amp;lt;/code&amp;gt;), and immediately clean up the apt cache (&amp;lt;code&amp;gt;rm -rf /var/lib/apt/lists/*&amp;lt;/code&amp;gt;) to keep the image size small. &amp;#039;&amp;#039;(Hint: Chain your commands with &amp;lt;code&amp;gt;&amp;amp;&amp;amp;&amp;lt;/code&amp;gt; and use &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; for multi-line formatting).&amp;#039;&amp;#039;&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Workspace:&amp;#039;&amp;#039;&amp;#039; Set the working directory inside the container to &amp;lt;code&amp;gt;/app&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;PID 1:&amp;#039;&amp;#039;&amp;#039; Set the default command (&amp;lt;code&amp;gt;CMD&amp;lt;/code&amp;gt;) to launch &amp;lt;code&amp;gt;/bin/bash&amp;lt;/code&amp;gt; so the container stays alive interactively.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Build and Test Your Image:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Once you have written your Dockerfile, test your infrastructure code by building and running it. It should behave exactly like your manual container did:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker build -t automated-arm-env:latest .&lt;br /&gt;
docker run -it --rm -v ${PWD}:/app automated-arm-env:latest&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
=== Assignment Submission ===&lt;br /&gt;
Upload &amp;#039;&amp;#039;&amp;#039;ONLY&amp;#039;&amp;#039;&amp;#039; your &amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt; to the Moodle VPL assignment. The automated grading server will run static analysis on your infrastructure-as-code syntax to verify your architecture setup, toolchain requirements, and layer optimization.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_5&amp;diff=8316</id>
		<title>SDPT Lab 5</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_5&amp;diff=8316"/>
		<updated>2026-03-30T13:52:27Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Week 5 Lab Activity: Containerization &amp;amp; Cross-Compilation =&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
This week, we eliminate the &amp;quot;It works on my machine&amp;quot; problem. You will learn how to build isolated Linux environments, cross-compile your &amp;lt;code&amp;gt;OvenController&amp;lt;/code&amp;gt; C++ code for an ARM architecture, and solve the complex problem of linking third-party static and dynamic libraries compiled for foreign architectures.&lt;br /&gt;
&lt;br /&gt;
We will accomplish this in three phases:&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Preparing CMake:&amp;#039;&amp;#039;&amp;#039; Updating the build system to link an external database library.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;The Manual Container (The &amp;quot;Old Way&amp;quot;):&amp;#039;&amp;#039;&amp;#039; Building the cross-compilation environment by hand to understand the underlying mechanics.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Infrastructure as Code (The &amp;quot;Modern Way&amp;quot;):&amp;#039;&amp;#039;&amp;#039; Automating the entire environment with a &amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 1: Preparing CMake for Foreign Libraries ==&lt;br /&gt;
Imagine our &amp;lt;code&amp;gt;OvenController&amp;lt;/code&amp;gt; needs to log telemetry data locally using an SQLite database. To do this, we need to link the &amp;lt;code&amp;gt;sqlite3&amp;lt;/code&amp;gt; library. &lt;br /&gt;
&lt;br /&gt;
Open your &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt; from Week 4 and add the standard linking commands. &amp;#039;&amp;#039;(Note: CMake is smart enough to look for the correct architecture version of this library based on the compiler we provide later).&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cmake&amp;quot;&amp;gt;&lt;br /&gt;
# Add this near the bottom of your CMakeLists.txt&lt;br /&gt;
find_package(PkgConfig REQUIRED)&lt;br /&gt;
pkg_check_modules(SQLITE3 REQUIRED sqlite3)&lt;br /&gt;
&lt;br /&gt;
# Add the includes and link the library to your executable&lt;br /&gt;
target_include_directories(unit_tests PRIVATE ${SQLITE3_INCLUDE_DIRS})&lt;br /&gt;
target_link_libraries(unit_tests PRIVATE ${SQLITE3_LIBRARIES})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 2: The Manual Container (The &amp;quot;Old Way&amp;quot;) ==&lt;br /&gt;
Before we automate, let&amp;#039;s understand what Docker is actually doing under the hood.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;1. Start a raw, interactive Ubuntu container:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Open your terminal and run a fresh Ubuntu 22.04 image, mounting your current code directory into &amp;lt;code&amp;gt;/app&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -it --name manual-build-env -v ${PWD}:/app ubuntu:22.04 /bin/bash&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Notice your terminal prompt has changed. You are now the root user inside an isolated Linux environment.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;2. The &amp;quot;Multiarch&amp;quot; Superpower:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
If we just run &amp;lt;code&amp;gt;apt-get install libsqlite3-dev&amp;lt;/code&amp;gt;, Ubuntu will download the &amp;lt;code&amp;gt;x86_64&amp;lt;/code&amp;gt; version. If we try to cross-compile our ARM code against it, the linker will violently crash. We must explicitly tell Ubuntu&amp;#039;s package manager to accept packages for a foreign architecture (&amp;lt;code&amp;gt;arm64&amp;lt;/code&amp;gt;).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dpkg --add-architecture arm64&lt;br /&gt;
apt-get update&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;3. Install the Toolchain and Foreign Libraries:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Now we install our cross-compiler, QEMU emulator, and the specifically compiled &amp;#039;&amp;#039;&amp;#039;ARM version&amp;#039;&amp;#039;&amp;#039; of our library (&amp;lt;code&amp;gt;:arm64&amp;lt;/code&amp;gt;).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
apt-get install -y build-essential cmake pkg-config g++-aarch64-linux-gnu qemu-user qemu-user-static&lt;br /&gt;
apt-get install -y libsqlite3-dev:arm64&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;4. Cross-Compile and Emulate:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Navigate to your mounted code and build the project for ARM. We use a command-line flag to tell CMake to use the ARM compiler instead of native GCC.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /app&lt;br /&gt;
mkdir build_arm &amp;amp;&amp;amp; cd build_arm&lt;br /&gt;
cmake -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ ..&lt;br /&gt;
make&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you try to run &amp;lt;code&amp;gt;./unit_tests&amp;lt;/code&amp;gt; natively, Linux will throw an &amp;lt;code&amp;gt;Exec format error&amp;lt;/code&amp;gt;. Use QEMU to emulate the execution of your ARM binary. Because we linked a dynamic library, we must tell QEMU where to find the ARM shared objects (&amp;lt;code&amp;gt;-L&amp;lt;/code&amp;gt; flag):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./unit_tests&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Verify that your Google Tests pass on the emulated architecture!&amp;#039;&amp;#039; Type &amp;lt;code&amp;gt;exit&amp;lt;/code&amp;gt; to leave and stop the container.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 3: Infrastructure as Code (The &amp;quot;Modern Way&amp;quot;) ==&lt;br /&gt;
Manually typing &amp;lt;code&amp;gt;apt-get&amp;lt;/code&amp;gt; commands, enabling architectures, and committing containers is tedious and error-prone. Modern DevOps engineers automate this using a &amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;1. Write the Dockerfile:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Create a file named exactly &amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt; (no extension) in your project root. Translate the manual steps you just took into an automated recipe.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;dockerfile&amp;quot;&amp;gt;&lt;br /&gt;
# 1. Base Image&lt;br /&gt;
FROM ubuntu:22.04&lt;br /&gt;
&lt;br /&gt;
# 2. Prevent interactive timezone prompts&lt;br /&gt;
ENV DEBIAN_FRONTEND=noninteractive&lt;br /&gt;
&lt;br /&gt;
# 3. Enable ARM64 Architecture for foreign libraries&lt;br /&gt;
RUN dpkg --add-architecture arm64&lt;br /&gt;
&lt;br /&gt;
# 4. Install toolchain &amp;amp; ARM libraries in ONE layer to save space&lt;br /&gt;
RUN apt-get update &amp;amp;&amp;amp; apt-get install -y \&lt;br /&gt;
    build-essential \&lt;br /&gt;
    cmake \&lt;br /&gt;
    pkg-config \&lt;br /&gt;
    g++-aarch64-linux-gnu \&lt;br /&gt;
    qemu-user \&lt;br /&gt;
    qemu-user-static \&lt;br /&gt;
    libsqlite3-dev:arm64 \&lt;br /&gt;
    &amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/*&lt;br /&gt;
&lt;br /&gt;
# 5. Set Workspace&lt;br /&gt;
WORKDIR /app&lt;br /&gt;
&lt;br /&gt;
# 6. Keep the container alive interactively&lt;br /&gt;
CMD [&amp;quot;/bin/bash&amp;quot;]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;2. Build the Automated Image:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Ask Docker Engine to read your recipe and build the image from scratch.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker build -t automated-arm-env:latest .&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;3. Run your Final Environment:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run -it --rm -v ${PWD}:/app automated-arm-env:latest&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
You now have a perfectly reproducible, portable embedded toolchain that natively resolves third-party ARM dependencies. &lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
=== Assignment Submission ===&lt;br /&gt;
Upload &amp;#039;&amp;#039;&amp;#039;ONLY&amp;#039;&amp;#039;&amp;#039; your &amp;lt;code&amp;gt;Dockerfile&amp;lt;/code&amp;gt; to the Moodle VPL assignment. The automated grading server will run static analysis on your infrastructure-as-code syntax to verify your architecture setup, toolchain requirements, and layer optimization.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_5&amp;diff=8315</id>
		<title>SDPT Lab 5</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_5&amp;diff=8315"/>
		<updated>2026-03-30T13:49:46Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: Pagină nouă: # Week 5 Lab Activity: Containerization &amp;amp; Cross-Compilation  ## Objective This week, we eliminate the &amp;quot;It works on my machine&amp;quot; problem. You will learn how to build isolated Linux e...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;# Week 5 Lab Activity: Containerization &amp;amp; Cross-Compilation&lt;br /&gt;
&lt;br /&gt;
## Objective&lt;br /&gt;
This week, we eliminate the &amp;quot;It works on my machine&amp;quot; problem. You will learn how to build isolated Linux environments, cross-compile your `OvenController` C++ code for an ARM architecture, and solve the complex problem of linking third-party static and dynamic libraries compiled for foreign architectures.&lt;br /&gt;
&lt;br /&gt;
We will accomplish this in three phases:&lt;br /&gt;
1. **Preparing CMake:** Updating the build system to link an external database library.&lt;br /&gt;
2. **The Manual Container (The &amp;quot;Old Way&amp;quot;):** Building the cross-compilation environment by hand to understand the underlying mechanics.&lt;br /&gt;
3. **Infrastructure as Code (The &amp;quot;Modern Way&amp;quot;):** Automating the entire environment with a `Dockerfile`.&lt;br /&gt;
&lt;br /&gt;
## Phase 1: Preparing CMake for Foreign Libraries&lt;br /&gt;
Imagine our `OvenController` needs to log telemetry data locally using an SQLite database. To do this, we need to link the `sqlite3` library. &lt;br /&gt;
&lt;br /&gt;
Open your `CMakeLists.txt` from Week 4 and add the standard linking commands. *(Note: CMake is smart enough to look for the correct architecture version of this library based on the compiler we provide later).*&lt;br /&gt;
&lt;br /&gt;
```cmake&lt;br /&gt;
# Add this near the bottom of your CMakeLists.txt&lt;br /&gt;
find_package(PkgConfig REQUIRED)&lt;br /&gt;
pkg_check_modules(SQLITE3 REQUIRED sqlite3)&lt;br /&gt;
&lt;br /&gt;
# Add the includes and link the library to your executable&lt;br /&gt;
target_include_directories(unit_tests PRIVATE ${SQLITE3_INCLUDE_DIRS})&lt;br /&gt;
target_link_libraries(unit_tests PRIVATE ${SQLITE3_LIBRARIES})&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
## Phase 2: The Manual Container (The &amp;quot;Old Way&amp;quot;)&lt;br /&gt;
Before we automate, let&amp;#039;s understand what Docker is actually doing under the hood.&lt;br /&gt;
&lt;br /&gt;
**1. Start a raw, interactive Ubuntu container:**&lt;br /&gt;
Open your terminal and run a fresh Ubuntu 22.04 image, mounting your current code directory into `/app`:&lt;br /&gt;
```bash&lt;br /&gt;
docker run -it --name manual-build-env -v ${PWD}:/app ubuntu:22.04 /bin/bash&lt;br /&gt;
```&lt;br /&gt;
*Notice your terminal prompt has changed. You are now the `root` user inside an isolated Linux environment.*&lt;br /&gt;
&lt;br /&gt;
**2. The &amp;quot;Multiarch&amp;quot; Superpower:**&lt;br /&gt;
If we just run `apt-get install libsqlite3-dev`, Ubuntu will download the `x86_64` version. If we try to cross-compile our ARM code against it, the linker will violently crash. We must explicitly tell Ubuntu&amp;#039;s package manager to accept packages for a foreign architecture (`arm64`).&lt;br /&gt;
```bash&lt;br /&gt;
dpkg --add-architecture arm64&lt;br /&gt;
apt-get update&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
**3. Install the Toolchain and Foreign Libraries:**&lt;br /&gt;
Now we install our cross-compiler, QEMU emulator, and the specifically compiled **ARM version** of our library (`:arm64`).&lt;br /&gt;
```bash&lt;br /&gt;
apt-get install -y build-essential cmake pkg-config g++-aarch64-linux-gnu qemu-user qemu-user-static&lt;br /&gt;
apt-get install -y libsqlite3-dev:arm64&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
**4. Cross-Compile and Emulate:**&lt;br /&gt;
Navigate to your mounted code and build the project for ARM. We use a command-line flag to tell CMake to use the ARM compiler instead of native GCC.&lt;br /&gt;
```bash&lt;br /&gt;
cd /app&lt;br /&gt;
mkdir build_arm &amp;amp;&amp;amp; cd build_arm&lt;br /&gt;
cmake -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ ..&lt;br /&gt;
make&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
If you try to run `./unit_tests` natively, Linux will throw an `Exec format error`. Use QEMU to emulate the execution of your ARM binary. Because we linked a dynamic library, we must tell QEMU where to find the ARM shared objects (`-L` flag):&lt;br /&gt;
```bash&lt;br /&gt;
qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./unit_tests&lt;br /&gt;
```&lt;br /&gt;
*Verify that your Google Tests pass on the emulated architecture!* Type `exit` to leave and stop the container.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
## Phase 3: Infrastructure as Code (The &amp;quot;Modern Way&amp;quot;)&lt;br /&gt;
Manually typing `apt-get` commands, enabling architectures, and committing containers is tedious and error-prone. Modern DevOps engineers automate this using a `Dockerfile`.&lt;br /&gt;
&lt;br /&gt;
**1. Write the Dockerfile:**&lt;br /&gt;
Create a file named exactly `Dockerfile` (no extension) in your project root. Translate the manual steps you just took into an automated recipe.&lt;br /&gt;
&lt;br /&gt;
```dockerfile&lt;br /&gt;
# 1. Base Image&lt;br /&gt;
FROM ubuntu:22.04&lt;br /&gt;
&lt;br /&gt;
# 2. Prevent interactive timezone prompts&lt;br /&gt;
ENV DEBIAN_FRONTEND=noninteractive&lt;br /&gt;
&lt;br /&gt;
# 3. Enable ARM64 Architecture for foreign libraries&lt;br /&gt;
RUN dpkg --add-architecture arm64&lt;br /&gt;
&lt;br /&gt;
# 4. Install toolchain &amp;amp; ARM libraries in ONE layer to save space&lt;br /&gt;
RUN apt-get update &amp;amp;&amp;amp; apt-get install -y \&lt;br /&gt;
    build-essential \&lt;br /&gt;
    cmake \&lt;br /&gt;
    pkg-config \&lt;br /&gt;
    g++-aarch64-linux-gnu \&lt;br /&gt;
    qemu-user \&lt;br /&gt;
    qemu-user-static \&lt;br /&gt;
    libsqlite3-dev:arm64 \&lt;br /&gt;
    &amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/*&lt;br /&gt;
&lt;br /&gt;
# 5. Set Workspace&lt;br /&gt;
WORKDIR /app&lt;br /&gt;
&lt;br /&gt;
# 6. Keep the container alive interactively&lt;br /&gt;
CMD [&amp;quot;/bin/bash&amp;quot;]&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
**2. Build the Automated Image:**&lt;br /&gt;
Ask Docker Engine to read your recipe and build the image from scratch.&lt;br /&gt;
```bash&lt;br /&gt;
docker build -t automated-arm-env:latest .&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
**3. Run your Final Environment:**&lt;br /&gt;
```bash&lt;br /&gt;
docker run -it --rm -v ${PWD}:/app automated-arm-env:latest&lt;br /&gt;
```&lt;br /&gt;
You now have a perfectly reproducible, portable embedded toolchain that natively resolves third-party ARM dependencies. &lt;br /&gt;
&lt;br /&gt;
### Assignment Submission&lt;br /&gt;
Upload **ONLY** your `Dockerfile` to the Moodle VPL assignment. The automated grading server will run static analysis on your infrastructure-as-code syntax to verify your architecture setup, toolchain requirements, and layer optimization.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=Software_Development_Process_and_Testing&amp;diff=8314</id>
		<title>Software Development Process and Testing</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=Software_Development_Process_and_Testing&amp;diff=8314"/>
		<updated>2026-03-30T13:47:36Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[SDPT Lab 1]]&lt;br /&gt;
* [[SDPT Lab 2]]&lt;br /&gt;
* [[SDPT Lab 3]]&lt;br /&gt;
* [[SDPT Lab 4]]&lt;br /&gt;
* [[SDPT Lab 5]]&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_4&amp;diff=8299</id>
		<title>SDPT Lab 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_4&amp;diff=8299"/>
		<updated>2026-03-23T13:32:44Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Lab 4: Software Verification - TDD, Mocking, and Code Coverage =&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
In traditional embedded systems, testing involves compiling code, flashing it to a board, and physically observing the hardware. This is slow, expensive, and scales poorly. Today, we implement &amp;quot;Shift-Left Testing.&amp;quot; We will verify our C++ logic on our Host PC using automated frameworks before it ever touches a microcontroller.&lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
* Integrate Google Test and Google Mock via CMake.&lt;br /&gt;
* Write Unit Tests using the AAA (Arrange, Act, Assert) pattern.&lt;br /&gt;
* Use Dependency Injection to decouple business logic from hardware registers.&lt;br /&gt;
* Simulate hardware interactions using Google Mock (GMock).&lt;br /&gt;
* Generate interactive HTML Code Coverage reports using &amp;lt;code&amp;gt;gcovr&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Part 1: Theoretical Reference ==&lt;br /&gt;
&amp;#039;&amp;#039;Use this section as a reference manual to complete the challenges in Part 2.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 1.1 Google Test &amp;amp; Mock Cheat Sheet ===&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Basic Assertions:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;EXPECT_EQ(actual, expected);&amp;lt;/code&amp;gt; (Non-fatal equality check)&lt;br /&gt;
* &amp;lt;code&amp;gt;EXPECT_FLOAT_EQ(actual, expected);&amp;lt;/code&amp;gt; (Safe float comparison)&lt;br /&gt;
* &amp;lt;code&amp;gt;EXPECT_TRUE(condition);&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Mocking an Interface (GMock):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MockSensor : public ISensor {&lt;br /&gt;
public:&lt;br /&gt;
    // MOCK_METHOD(ReturnType, MethodName, (Arguments), (override));&lt;br /&gt;
    MOCK_METHOD(float, read_temperature, (), (override));&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Setting Mock Expectations:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MockSensor fake_sensor;&lt;br /&gt;
// Program the mock to return 45.0 exactly twice.&lt;br /&gt;
EXPECT_CALL(fake_sensor, read_temperature())&lt;br /&gt;
    .Times(2)&lt;br /&gt;
    .WillRepeatedly(testing::Return(45.0f));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1.2 CMake Debug &amp;amp; Coverage Setup ===&lt;br /&gt;
Coverage mathematically requires a completely unoptimized binary mapping exactly to your source code lines.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if(CMAKE_BUILD_TYPE STREQUAL &amp;quot;Debug&amp;quot;)&lt;br /&gt;
    target_compile_options(my_target PRIVATE -O0 -g --coverage)&lt;br /&gt;
    target_link_options(my_target PRIVATE --coverage)&lt;br /&gt;
endif()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1.3 Running gcovr ===&lt;br /&gt;
Execute this from inside your &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory after running the tests:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcovr -r ../ . --html --html-details -o coverage.html -e &amp;quot;.*_deps.*&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1.4 Official Documentation &amp;amp; Tutorials ===&lt;br /&gt;
When you get stuck on syntax or advanced features during the lab, refer to these official resources:&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Google Test:&amp;#039;&amp;#039;&amp;#039; [https://google.github.io/googletest/primer.html Googletest Primer (Official Tutorial)]&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Google Mock:&amp;#039;&amp;#039;&amp;#039; [https://google.github.io/googletest/gmock_for_dummies.html gMock for Dummies] and the [https://google.github.io/googletest/reference/mocking.html Mocking Reference]&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;CMake FetchContent:&amp;#039;&amp;#039;&amp;#039; [https://cmake.org/cmake/help/latest/module/FetchContent.html Official CMake FetchContent Documentation]&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Code Coverage (gcovr):&amp;#039;&amp;#039;&amp;#039; [https://gcovr.com/en/stable/guide.html gcovr User Guide]&lt;br /&gt;
&lt;br /&gt;
== Part 2: The Challenges ==&lt;br /&gt;
&lt;br /&gt;
=== Setup: The Raw Materials ===&lt;br /&gt;
You are building the safety controller for an industrial oven. It must read temperatures from an I2C sensor and trigger a physical alarm if it overheats. &lt;br /&gt;
&lt;br /&gt;
Create a new workspace (&amp;lt;code&amp;gt;sdpt-lab4&amp;lt;/code&amp;gt;). Create &amp;lt;code&amp;gt;include/&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;src/&amp;lt;/code&amp;gt; directories. Populate them with these three files:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;include/ISensor.h&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039; (The Hardware Interface)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#pragma once&lt;br /&gt;
&lt;br /&gt;
// Pure virtual interface. We DO NOT implement hardware logic here.&lt;br /&gt;
class ISensor {&lt;br /&gt;
public:&lt;br /&gt;
    virtual float read_temperature() = 0;&lt;br /&gt;
    virtual ~ISensor() = default;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;include/OvenController.h&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039; (The Logic Module)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#pragma once&lt;br /&gt;
#include &amp;quot;ISensor.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
class OvenController {&lt;br /&gt;
private:&lt;br /&gt;
    ISensor* temp_sensor;&lt;br /&gt;
    bool alarm_active;&lt;br /&gt;
    float max_safe_temp;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    // Constructor uses Dependency Injection!&lt;br /&gt;
    OvenController(ISensor* sensor, float safe_limit = 250.0f);&lt;br /&gt;
    &lt;br /&gt;
    void check_safety();&lt;br /&gt;
    bool is_alarm_active() const;&lt;br /&gt;
    &lt;br /&gt;
    // Pure math function&lt;br /&gt;
    static float raw_adc_to_celsius(int adc_value);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;src/OvenController.cpp&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039; (The Buggy Implementation)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;quot;../include/OvenController.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
OvenController::OvenController(ISensor* sensor, float safe_limit) &lt;br /&gt;
    : temp_sensor(sensor), alarm_active(false), max_safe_temp(safe_limit) {}&lt;br /&gt;
&lt;br /&gt;
void OvenController::check_safety() {&lt;br /&gt;
    float current_temp = temp_sensor-&amp;gt;read_temperature();&lt;br /&gt;
    &lt;br /&gt;
    // BUG 1: It only triggers if STRICTLY greater. What if it equals the limit?&lt;br /&gt;
    if (current_temp &amp;gt; max_safe_temp) {&lt;br /&gt;
        alarm_active = true;&lt;br /&gt;
    } else {&lt;br /&gt;
        alarm_active = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
bool OvenController::is_alarm_active() const {&lt;br /&gt;
    return alarm_active;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float OvenController::raw_adc_to_celsius(int adc_value) {&lt;br /&gt;
    // BUG 2: Integer division truncates the decimal! (e.g., 5/2 = 2, not 2.5)&lt;br /&gt;
    return (adc_value / 4095) * 330.0f; &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Challenge 1: The Verification Build System (Estimated: 20 mins) ===&lt;br /&gt;
We need a build system that fetches Google Test and compiles our code with coverage instrumentation.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt; in the root directory.&lt;br /&gt;
# Build a static library named &amp;lt;code&amp;gt;oven_lib&amp;lt;/code&amp;gt; containing &amp;lt;code&amp;gt;src/OvenController.cpp&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use &amp;lt;code&amp;gt;FetchContent&amp;lt;/code&amp;gt; to pull Google Test (&amp;lt;code&amp;gt;https://github.com/google/googletest.git&amp;lt;/code&amp;gt;, tag &amp;lt;code&amp;gt;v1.13.0&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Create an executable named &amp;lt;code&amp;gt;unit_tests&amp;lt;/code&amp;gt;. (You will create &amp;lt;code&amp;gt;tests/test_oven.cpp&amp;lt;/code&amp;gt; in the next step).&lt;br /&gt;
# Link &amp;lt;code&amp;gt;oven_lib&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;gtest_main&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;gmock&amp;lt;/code&amp;gt; to your test executable.&lt;br /&gt;
# Add the CMake logic to inject &amp;lt;code&amp;gt;-O0 -g --coverage&amp;lt;/code&amp;gt; ONLY if the build type is &amp;quot;Debug&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Verification:&amp;#039;&amp;#039;&amp;#039; Run &amp;lt;code&amp;gt;cmake -DCMAKE_BUILD_TYPE=Debug ..&amp;lt;/code&amp;gt; inside your build folder. It must configure without errors and download GTest.&lt;br /&gt;
&lt;br /&gt;
=== Challenge 2: Pure Math TDD (Estimated: 25 mins) ===&lt;br /&gt;
Let&amp;#039;s catch the integer division bug using the Red-Green-Refactor cycle.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;tests/&amp;lt;/code&amp;gt; directory and a &amp;lt;code&amp;gt;tests/test_oven.cpp&amp;lt;/code&amp;gt; file.&lt;br /&gt;
# Include &amp;lt;code&amp;gt;&amp;lt;gtest/gtest.h&amp;gt;&amp;lt;/code&amp;gt; and your &amp;lt;code&amp;gt;OvenController.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Write a &amp;lt;code&amp;gt;TEST(MathTest, ConvertsADCToCelsius)&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use &amp;lt;code&amp;gt;EXPECT_FLOAT_EQ&amp;lt;/code&amp;gt; to assert that an ADC value of &amp;lt;code&amp;gt;2047&amp;lt;/code&amp;gt; (roughly half of 4095) returns approximately &amp;lt;code&amp;gt;164.957f&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Compile and run &amp;lt;code&amp;gt;./unit_tests&amp;lt;/code&amp;gt;. (Watch it fail! This is the RED phase).&lt;br /&gt;
# Refactor &amp;lt;code&amp;gt;OvenController.cpp&amp;lt;/code&amp;gt; to fix the integer division bug. Recompile. (Watch it pass! This is the GREEN phase).&lt;br /&gt;
&lt;br /&gt;
=== Challenge 3: Hardware Mocking (Estimated: 40 mins) ===&lt;br /&gt;
We need to test &amp;lt;code&amp;gt;check_safety()&amp;lt;/code&amp;gt;, but we are on a PC. We have no I2C hardware. We must mock the &amp;lt;code&amp;gt;ISensor&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# In your test file, include &amp;lt;code&amp;gt;&amp;lt;gmock/gmock.h&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;MockSensor&amp;lt;/code&amp;gt; class that inherits from &amp;lt;code&amp;gt;ISensor&amp;lt;/code&amp;gt;. Use &amp;lt;code&amp;gt;MOCK_METHOD&amp;lt;/code&amp;gt; to mock &amp;lt;code&amp;gt;read_temperature&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Write a &amp;lt;code&amp;gt;TEST(SafetyTest, TriggersAlarmOnOverheat)&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* &amp;#039;&amp;#039;&amp;#039;Arrange:&amp;#039;&amp;#039;&amp;#039; Instantiate the MockSensor. Instantiate the OvenController, injecting the mock sensor into it with a safe limit of 250.0f.&lt;br /&gt;
#* &amp;#039;&amp;#039;&amp;#039;Expectation:&amp;#039;&amp;#039;&amp;#039; Program the mock to return &amp;lt;code&amp;gt;260.0f&amp;lt;/code&amp;gt; when called.&lt;br /&gt;
#* &amp;#039;&amp;#039;&amp;#039;Act:&amp;#039;&amp;#039;&amp;#039; Call &amp;lt;code&amp;gt;check_safety()&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* &amp;#039;&amp;#039;&amp;#039;Assert:&amp;#039;&amp;#039;&amp;#039; Expect that &amp;lt;code&amp;gt;is_alarm_active()&amp;lt;/code&amp;gt; is true.&lt;br /&gt;
# Write a second test: &amp;lt;code&amp;gt;TEST(SafetyTest, TriggersAlarmExactlyAtLimit)&amp;lt;/code&amp;gt;. &lt;br /&gt;
#* Program the mock to return exactly &amp;lt;code&amp;gt;250.0f&amp;lt;/code&amp;gt;. &lt;br /&gt;
#* Run the test. It will FAIL due to Bug 1. Fix the production code so it triggers on `&amp;gt;=`.&lt;br /&gt;
&lt;br /&gt;
=== Challenge 4: The Coverage Report (Estimated: 15 mins) ===&lt;br /&gt;
Did we test every branch of our code? Let&amp;#039;s prove it mathematically.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Ensure you have run &amp;lt;code&amp;gt;./unit_tests&amp;lt;/code&amp;gt; at least once so the &amp;lt;code&amp;gt;.gcda&amp;lt;/code&amp;gt; files are generated.&lt;br /&gt;
# Run the &amp;lt;code&amp;gt;gcovr&amp;lt;/code&amp;gt; command provided in the Theoretical Reference section.&lt;br /&gt;
# Open the resulting &amp;lt;code&amp;gt;coverage.html&amp;lt;/code&amp;gt; file in your web browser. Check that you have achieved 100% branch coverage.&lt;br /&gt;
&lt;br /&gt;
== Submission and Evaluation (Moodle VPL) ==&lt;br /&gt;
For this lab, your work will be automatically graded by the Moodle Virtual Programming Lab (VPL) engine. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;How to submit:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Ensure your code compiles locally and all tests pass (Green).&lt;br /&gt;
# Do &amp;#039;&amp;#039;&amp;#039;NOT&amp;#039;&amp;#039;&amp;#039; upload your &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory or any generated HTML files.&lt;br /&gt;
# Select the following files from your workspace:&lt;br /&gt;
#* &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;include/ISensor.h&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;include/OvenController.h&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;src/OvenController.cpp&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;tests/test_oven.cpp&amp;lt;/code&amp;gt;&lt;br /&gt;
# Package these files into a single &amp;lt;code&amp;gt;.zip&amp;lt;/code&amp;gt; archive (maintaining the folder structure).&lt;br /&gt;
# Go to the Lab 4 assignment on Moodle and upload your &amp;lt;code&amp;gt;.zip&amp;lt;/code&amp;gt; file into the VPL submission portal.&lt;br /&gt;
# Click the &amp;#039;&amp;#039;&amp;#039;Evaluate&amp;#039;&amp;#039;&amp;#039; button.&lt;br /&gt;
&lt;br /&gt;
The VPL server will automatically compile your CMake project, execute your Google Tests, and run &amp;lt;code&amp;gt;gcovr&amp;lt;/code&amp;gt;. Your grade will be calculated based on the number of passing tests and the percentage of branch coverage achieved.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_4&amp;diff=8298</id>
		<title>SDPT Lab 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_4&amp;diff=8298"/>
		<updated>2026-03-23T13:27:18Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: Pagină nouă: = Lab 4: Software Verification - TDD, Mocking, and Code Coverage =  == Introduction == In traditional embedded systems, testing involves compiling code, flashing it to a board, and...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Lab 4: Software Verification - TDD, Mocking, and Code Coverage =&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
In traditional embedded systems, testing involves compiling code, flashing it to a board, and physically observing the hardware. This is slow, expensive, and scales poorly. Today, we implement &amp;quot;Shift-Left Testing.&amp;quot; We will verify our C++ logic on our Host PC using automated frameworks before it ever touches a microcontroller.&lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
* Integrate Google Test and Google Mock via CMake.&lt;br /&gt;
* Write Unit Tests using the AAA (Arrange, Act, Assert) pattern.&lt;br /&gt;
* Use Dependency Injection to decouple business logic from hardware registers.&lt;br /&gt;
* Simulate hardware interactions using Google Mock (GMock).&lt;br /&gt;
* Generate interactive HTML Code Coverage reports using &amp;lt;code&amp;gt;gcovr&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Part 1: Theoretical Reference ==&lt;br /&gt;
&amp;#039;&amp;#039;Use this section as a reference manual to complete the challenges in Part 2.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 1.1 Google Test &amp;amp; Mock Cheat Sheet ===&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Basic Assertions:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;EXPECT_EQ(actual, expected);&amp;lt;/code&amp;gt; (Non-fatal equality check)&lt;br /&gt;
* &amp;lt;code&amp;gt;EXPECT_FLOAT_EQ(actual, expected);&amp;lt;/code&amp;gt; (Safe float comparison)&lt;br /&gt;
* &amp;lt;code&amp;gt;EXPECT_TRUE(condition);&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Mocking an Interface (GMock):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class MockSensor : public ISensor {&lt;br /&gt;
public:&lt;br /&gt;
    // MOCK_METHOD(ReturnType, MethodName, (Arguments), (override));&lt;br /&gt;
    MOCK_METHOD(float, read_temperature, (), (override));&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Setting Mock Expectations:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MockSensor fake_sensor;&lt;br /&gt;
// Program the mock to return 45.0 exactly twice.&lt;br /&gt;
EXPECT_CALL(fake_sensor, read_temperature())&lt;br /&gt;
    .Times(2)&lt;br /&gt;
    .WillRepeatedly(testing::Return(45.0f));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1.2 CMake Debug &amp;amp; Coverage Setup ===&lt;br /&gt;
Coverage mathematically requires a completely unoptimized binary mapping exactly to your source code lines.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if(CMAKE_BUILD_TYPE STREQUAL &amp;quot;Debug&amp;quot;)&lt;br /&gt;
    target_compile_options(my_target PRIVATE -O0 -g --coverage)&lt;br /&gt;
    target_link_options(my_target PRIVATE --coverage)&lt;br /&gt;
endif()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1.3 Running gcovr ===&lt;br /&gt;
Execute this from inside your &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory after running the tests:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcovr -r ../ . --html --html-details -o coverage.html -e &amp;quot;.*_deps.*&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Part 2: The Challenges ==&lt;br /&gt;
&lt;br /&gt;
=== Setup: The Raw Materials ===&lt;br /&gt;
You are building the safety controller for an industrial oven. It must read temperatures from an I2C sensor and trigger a physical alarm if it overheats. &lt;br /&gt;
&lt;br /&gt;
Create a new workspace (&amp;lt;code&amp;gt;sdpt-lab4&amp;lt;/code&amp;gt;). Create &amp;lt;code&amp;gt;include/&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;src/&amp;lt;/code&amp;gt; directories. Populate them with these three files:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;include/ISensor.h&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039; (The Hardware Interface)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#pragma once&lt;br /&gt;
&lt;br /&gt;
// Pure virtual interface. We DO NOT implement hardware logic here.&lt;br /&gt;
class ISensor {&lt;br /&gt;
public:&lt;br /&gt;
    virtual float read_temperature() = 0;&lt;br /&gt;
    virtual ~ISensor() = default;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;include/OvenController.h&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039; (The Logic Module)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#pragma once&lt;br /&gt;
#include &amp;quot;ISensor.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
class OvenController {&lt;br /&gt;
private:&lt;br /&gt;
    ISensor* temp_sensor;&lt;br /&gt;
    bool alarm_active;&lt;br /&gt;
    float max_safe_temp;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    // Constructor uses Dependency Injection!&lt;br /&gt;
    OvenController(ISensor* sensor, float safe_limit = 250.0f);&lt;br /&gt;
    &lt;br /&gt;
    void check_safety();&lt;br /&gt;
    bool is_alarm_active() const;&lt;br /&gt;
    &lt;br /&gt;
    // Pure math function&lt;br /&gt;
    static float raw_adc_to_celsius(int adc_value);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;src/OvenController.cpp&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039; (The Buggy Implementation)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;quot;../include/OvenController.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
OvenController::OvenController(ISensor* sensor, float safe_limit) &lt;br /&gt;
    : temp_sensor(sensor), alarm_active(false), max_safe_temp(safe_limit) {}&lt;br /&gt;
&lt;br /&gt;
void OvenController::check_safety() {&lt;br /&gt;
    float current_temp = temp_sensor-&amp;gt;read_temperature();&lt;br /&gt;
    &lt;br /&gt;
    // BUG 1: It only triggers if STRICTLY greater. What if it equals the limit?&lt;br /&gt;
    if (current_temp &amp;gt; max_safe_temp) {&lt;br /&gt;
        alarm_active = true;&lt;br /&gt;
    } else {&lt;br /&gt;
        alarm_active = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
bool OvenController::is_alarm_active() const {&lt;br /&gt;
    return alarm_active;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float OvenController::raw_adc_to_celsius(int adc_value) {&lt;br /&gt;
    // BUG 2: Integer division truncates the decimal! (e.g., 5/2 = 2, not 2.5)&lt;br /&gt;
    return (adc_value / 4095) * 330.0f; &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Challenge 1: The Verification Build System (Estimated: 20 mins) ===&lt;br /&gt;
We need a build system that fetches Google Test and compiles our code with coverage instrumentation.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt; in the root directory.&lt;br /&gt;
# Build a static library named &amp;lt;code&amp;gt;oven_lib&amp;lt;/code&amp;gt; containing &amp;lt;code&amp;gt;src/OvenController.cpp&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use &amp;lt;code&amp;gt;FetchContent&amp;lt;/code&amp;gt; to pull Google Test (&amp;lt;code&amp;gt;https://github.com/google/googletest.git&amp;lt;/code&amp;gt;, tag &amp;lt;code&amp;gt;v1.13.0&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Create an executable named &amp;lt;code&amp;gt;unit_tests&amp;lt;/code&amp;gt;. (You will create &amp;lt;code&amp;gt;tests/test_oven.cpp&amp;lt;/code&amp;gt; in the next step).&lt;br /&gt;
# Link &amp;lt;code&amp;gt;oven_lib&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;gtest_main&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;gmock&amp;lt;/code&amp;gt; to your test executable.&lt;br /&gt;
# Add the CMake logic to inject &amp;lt;code&amp;gt;-O0 -g --coverage&amp;lt;/code&amp;gt; ONLY if the build type is &amp;quot;Debug&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Verification:&amp;#039;&amp;#039;&amp;#039; Run &amp;lt;code&amp;gt;cmake -DCMAKE_BUILD_TYPE=Debug ..&amp;lt;/code&amp;gt; inside your build folder. It must configure without errors and download GTest.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Challenge 2: Pure Math TDD (Estimated: 25 mins) ===&lt;br /&gt;
Let&amp;#039;s catch the integer division bug using the Red-Green-Refactor cycle.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;tests/&amp;lt;/code&amp;gt; directory and a &amp;lt;code&amp;gt;tests/test_oven.cpp&amp;lt;/code&amp;gt; file.&lt;br /&gt;
# Include &amp;lt;code&amp;gt;&amp;lt;gtest/gtest.h&amp;gt;&amp;lt;/code&amp;gt; and your &amp;lt;code&amp;gt;OvenController.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Write a &amp;lt;code&amp;gt;TEST(MathTest, ConvertsADCToCelsius)&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use &amp;lt;code&amp;gt;EXPECT_FLOAT_EQ&amp;lt;/code&amp;gt; to assert that an ADC value of &amp;lt;code&amp;gt;2047&amp;lt;/code&amp;gt; (roughly half of 4095) returns approximately &amp;lt;code&amp;gt;164.957f&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Compile and run &amp;lt;code&amp;gt;./unit_tests&amp;lt;/code&amp;gt;. (Watch it fail! This is the RED phase).&lt;br /&gt;
# Refactor &amp;lt;code&amp;gt;OvenController.cpp&amp;lt;/code&amp;gt; to fix the integer division bug. Recompile. (Watch it pass! This is the GREEN phase).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Challenge 3: Hardware Mocking (Estimated: 40 mins) ===&lt;br /&gt;
We need to test &amp;lt;code&amp;gt;check_safety()&amp;lt;/code&amp;gt;, but we are on a PC. We have no I2C hardware. We must mock the &amp;lt;code&amp;gt;ISensor&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# In your test file, include &amp;lt;code&amp;gt;&amp;lt;gmock/gmock.h&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;MockSensor&amp;lt;/code&amp;gt; class that inherits from &amp;lt;code&amp;gt;ISensor&amp;lt;/code&amp;gt;. Use &amp;lt;code&amp;gt;MOCK_METHOD&amp;lt;/code&amp;gt; to mock &amp;lt;code&amp;gt;read_temperature&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Write a &amp;lt;code&amp;gt;TEST(SafetyTest, TriggersAlarmOnOverheat)&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* &amp;#039;&amp;#039;&amp;#039;Arrange:&amp;#039;&amp;#039;&amp;#039; Instantiate the MockSensor. Instantiate the OvenController, injecting the mock sensor into it with a safe limit of 250.0f.&lt;br /&gt;
#* &amp;#039;&amp;#039;&amp;#039;Expectation:&amp;#039;&amp;#039;&amp;#039; Program the mock to return &amp;lt;code&amp;gt;260.0f&amp;lt;/code&amp;gt; when called.&lt;br /&gt;
#* &amp;#039;&amp;#039;&amp;#039;Act:&amp;#039;&amp;#039;&amp;#039; Call &amp;lt;code&amp;gt;check_safety()&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* &amp;#039;&amp;#039;&amp;#039;Assert:&amp;#039;&amp;#039;&amp;#039; Expect that &amp;lt;code&amp;gt;is_alarm_active()&amp;lt;/code&amp;gt; is true.&lt;br /&gt;
# Write a second test: &amp;lt;code&amp;gt;TEST(SafetyTest, TriggersAlarmExactlyAtLimit)&amp;lt;/code&amp;gt;. &lt;br /&gt;
#* Program the mock to return exactly &amp;lt;code&amp;gt;250.0f&amp;lt;/code&amp;gt;. &lt;br /&gt;
#* Run the test. It will FAIL due to Bug 1. Fix the production code so it triggers on `&amp;gt;=`.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Challenge 4: The Coverage Report (Estimated: 15 mins) ===&lt;br /&gt;
Did we test every branch of our code? Let&amp;#039;s prove it mathematically.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Ensure you have run &amp;lt;code&amp;gt;./unit_tests&amp;lt;/code&amp;gt; at least once so the &amp;lt;code&amp;gt;.gcda&amp;lt;/code&amp;gt; files are generated.&lt;br /&gt;
# Run the &amp;lt;code&amp;gt;gcovr&amp;lt;/code&amp;gt; command provided in the Theoretical Reference section.&lt;br /&gt;
# Open the resulting &amp;lt;code&amp;gt;coverage.html&amp;lt;/code&amp;gt; file in your web browser.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Verification:&amp;#039;&amp;#039;&amp;#039; Click on the &amp;lt;code&amp;gt;OvenController.cpp&amp;lt;/code&amp;gt; file in the HTML report. You should see 100% line coverage and 100% branch coverage (green lines). If you have red lines, you are missing a test case!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Lab Evaluation ==&lt;br /&gt;
To receive full credit, call the professor/TA to your workstation and demonstrate:&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./unit_tests&amp;lt;/code&amp;gt;. All tests must pass (Green).&lt;br /&gt;
# Show your test code, explaining how Dependency Injection allowed you to pass the &amp;lt;code&amp;gt;MockSensor&amp;lt;/code&amp;gt; into the controller.&lt;br /&gt;
# Open your &amp;lt;code&amp;gt;coverage.html&amp;lt;/code&amp;gt; report in the browser, demonstrating 100% branch coverage for the &amp;lt;code&amp;gt;OvenController.cpp&amp;lt;/code&amp;gt; file.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=Software_Development_Process_and_Testing&amp;diff=8297</id>
		<title>Software Development Process and Testing</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=Software_Development_Process_and_Testing&amp;diff=8297"/>
		<updated>2026-03-23T13:26:31Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[SDPT Lab 1]]&lt;br /&gt;
* [[SDPT Lab 2]]&lt;br /&gt;
* [[SDPT Lab 3]]&lt;br /&gt;
* [[SDPT Lab 4]]&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_3&amp;diff=8292</id>
		<title>SDPT Lab 3</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_3&amp;diff=8292"/>
		<updated>2026-03-16T17:07:57Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Lab 3: Build Automation - Makefiles and Modern CMake =&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
In professional embedded development, clicking a &amp;quot;Build&amp;quot; button in an IDE is a luxury you rarely have. When working with Embedded Linux, RTOS environments, or CI/CD pipelines, you must define exactly how your source code is translated into machine code. &lt;br /&gt;
&lt;br /&gt;
This lab transitions you from manual terminal commands to scalable build automation. &lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
* Understand the C++ compilation pipeline (Preprocessing $\rightarrow$ Compilation $\rightarrow$ Linking).&lt;br /&gt;
* Master GNU Make: pattern rules, automatic variables, and header dependency generation.&lt;br /&gt;
* Master Modern CMake: out-of-source builds, targets, and static libraries.&lt;br /&gt;
* Integrate remote third-party libraries using CMake &amp;lt;code&amp;gt;FetchContent&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Part 1: Theoretical Reference ==&lt;br /&gt;
&amp;#039;&amp;#039;Use this section as a reference manual to complete the tasks in Part 2.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 1.1 GNU Make Fundamentals ===&lt;br /&gt;
Make tracks file modification timestamps to avoid recompiling code that hasn&amp;#039;t changed. A &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; consists of rules:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;make&amp;quot;&amp;gt;&lt;br /&gt;
target: dependencies&lt;br /&gt;
&amp;lt;TAB&amp;gt; command&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;(Note: Makefiles strictly require a real TAB character for indentation, not spaces!)&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Automatic Variables:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Make provides shortcuts to avoid typing duplicate filenames:&lt;br /&gt;
* &amp;lt;code&amp;gt;$@&amp;lt;/code&amp;gt; : The target filename.&lt;br /&gt;
* &amp;lt;code&amp;gt;$&amp;lt;&amp;lt;/code&amp;gt; : The first dependency.&lt;br /&gt;
* &amp;lt;code&amp;gt;$^&amp;lt;/code&amp;gt; : All dependencies (space-separated).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Pattern Rules:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Instead of writing a rule for every file, use a pattern template:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;make&amp;quot;&amp;gt;&lt;br /&gt;
%.o: %.cpp&lt;br /&gt;
	$(CXX) $(CXXFLAGS) -c $&amp;lt; -o $@&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;GCC Auto-Dependencies (The Header Problem):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
If you change a &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; file, Make won&amp;#039;t normally detect it because object files depend on &amp;lt;code&amp;gt;.cpp&amp;lt;/code&amp;gt; files. We ask GCC to generate dependency (&amp;lt;code&amp;gt;.d&amp;lt;/code&amp;gt;) files for us:&lt;br /&gt;
* Add &amp;lt;code&amp;gt;-MMD -MP&amp;lt;/code&amp;gt; to your &amp;lt;code&amp;gt;CXXFLAGS&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Include the generated files at the bottom of your Makefile using: &amp;lt;code&amp;gt;-include $(DEPS)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1.2 Modern CMake Fundamentals ===&lt;br /&gt;
CMake is a meta-build system. It generates Makefiles (or Ninja files, or Visual Studio solutions) based on a high-level &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt; script. Modern CMake is &amp;quot;Target-Based&amp;quot;—you define targets (executables/libraries) and attach properties to them.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Core Commands:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cmake&amp;quot;&amp;gt;&lt;br /&gt;
cmake_minimum_required(VERSION 3.10)&lt;br /&gt;
project(MyProject CXX)&lt;br /&gt;
&lt;br /&gt;
# Build an executable from source&lt;br /&gt;
add_executable(my_app main.cpp)&lt;br /&gt;
&lt;br /&gt;
# Build a static library (.a archive)&lt;br /&gt;
add_library(my_driver STATIC driver.cpp)&lt;br /&gt;
&lt;br /&gt;
# Define where a target should look for header files&lt;br /&gt;
target_include_directories(my_driver PUBLIC include/)&lt;br /&gt;
&lt;br /&gt;
# Link a library to an executable&lt;br /&gt;
target_link_libraries(my_app PRIVATE my_driver)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Out-of-Source Builds:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Never pollute your source directory with binaries. Always build in a separate folder:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mkdir build &amp;amp;&amp;amp; cd build&lt;br /&gt;
cmake ..&lt;br /&gt;
make&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Fetching External Libraries:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
CMake can download libraries directly from Git during the configuration phase:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cmake&amp;quot;&amp;gt;&lt;br /&gt;
include(FetchContent)&lt;br /&gt;
FetchContent_Declare(&lt;br /&gt;
  json_lib&lt;br /&gt;
  GIT_REPOSITORY https://github.com/nlohmann/json.git&lt;br /&gt;
  GIT_TAG        v3.11.2&lt;br /&gt;
)&lt;br /&gt;
FetchContent_MakeAvailable(json_lib)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1.3 Useful Resources ===&lt;br /&gt;
* [https://www.gnu.org/software/make/manual/make.html GNU Make Manual]&lt;br /&gt;
* [https://cmake.org/cmake/help/latest/ CMake Official Documentation]&lt;br /&gt;
&lt;br /&gt;
== Part 2: The Challenges ==&lt;br /&gt;
&lt;br /&gt;
=== Setup: The Raw Materials ===&lt;br /&gt;
Create a new directory for this lab (&amp;lt;code&amp;gt;sdpt-lab3&amp;lt;/code&amp;gt;). Inside, create an &amp;lt;code&amp;gt;include/&amp;lt;/code&amp;gt; directory and a &amp;lt;code&amp;gt;src/&amp;lt;/code&amp;gt; directory. Populate them with the following three files to simulate an IoT sensor node.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;include/sensor.h&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#pragma once&lt;br /&gt;
&lt;br /&gt;
struct SensorData {&lt;br /&gt;
    int temperature;&lt;br /&gt;
    int humidity;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void init_sensor();&lt;br /&gt;
SensorData read_sensor();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;src/sensor.cpp&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
#include &amp;quot;../include/sensor.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void init_sensor() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;[Hardware] I2C Sensor Initialized.&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
SensorData read_sensor() {&lt;br /&gt;
    return {24, 60};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;src/main.cpp&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
#include &amp;quot;../include/sensor.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Starting IoT Node...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    init_sensor();&lt;br /&gt;
    &lt;br /&gt;
    SensorData data = read_sensor();&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Temp: &amp;quot; &amp;lt;&amp;lt; data.temperature &amp;lt;&amp;lt; &amp;quot;C, Hum: &amp;quot; &amp;lt;&amp;lt; data.humidity &amp;lt;&amp;lt; &amp;quot;%&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Challenge 1: The Scalable Makefile (Estimated time: 25 mins) ===&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039; Write a &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; in the root directory that compiles these files into an executable named &amp;lt;code&amp;gt;iot_node.bin&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Do &amp;#039;&amp;#039;&amp;#039;not&amp;#039;&amp;#039;&amp;#039; hardcode the &amp;lt;code&amp;gt;.cpp&amp;lt;/code&amp;gt; file names. Use the &amp;lt;code&amp;gt;wildcard&amp;lt;/code&amp;gt; function to find them dynamically.&lt;br /&gt;
* Use variables for the compiler (&amp;lt;code&amp;gt;CXX&amp;lt;/code&amp;gt;) and flags (&amp;lt;code&amp;gt;CXXFLAGS&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Use Pattern Rules and Automatic Variables to compile &amp;lt;code&amp;gt;.cpp&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;.o&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Implement GCC header dependency tracking (&amp;lt;code&amp;gt;-MMD -MP&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Verification:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. It should compile successfully. &lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; again immediately. It should say &amp;quot;Nothing to be done&amp;quot;.&lt;br /&gt;
# Open &amp;lt;code&amp;gt;include/sensor.h&amp;lt;/code&amp;gt; and add a dummy integer to the &amp;lt;code&amp;gt;SensorData&amp;lt;/code&amp;gt; struct. Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; again. It MUST recompile both &amp;lt;code&amp;gt;.cpp&amp;lt;/code&amp;gt; files automatically. If it doesn&amp;#039;t, your dependency tracking is broken.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Challenge 2: Migrating to CMake (Estimated time: 20 mins) ===&lt;br /&gt;
Makefiles are not cross-platform. We are moving to CMake.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
# Run &amp;lt;code&amp;gt;make clean&amp;lt;/code&amp;gt; (or manually delete all generated &amp;lt;code&amp;gt;.o&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.d&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;.bin&amp;lt;/code&amp;gt; files).&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt; file to build the exact same executable.&lt;br /&gt;
# Set the C++ standard to C++14.&lt;br /&gt;
# Perform an &amp;#039;&amp;#039;&amp;#039;Out-of-Source build&amp;#039;&amp;#039;&amp;#039; using a &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Verification:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
Your root directory should contain only your source files and the &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt;. Inside the &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory, running &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; should yield the executable.&lt;br /&gt;
&lt;br /&gt;
=== Challenge 3: Modular Architecture (Estimated time: 25 mins) ===&lt;br /&gt;
Dumping all source files into a single executable is bad practice. Hardware drivers should be isolated into static libraries.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039; Modify your &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Remove &amp;lt;code&amp;gt;src/sensor.cpp&amp;lt;/code&amp;gt; from your executable target.&lt;br /&gt;
# Create a new STATIC library target named &amp;lt;code&amp;gt;sensor_driver&amp;lt;/code&amp;gt; from &amp;lt;code&amp;gt;src/sensor.cpp&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Attach the &amp;lt;code&amp;gt;include/&amp;lt;/code&amp;gt; directory to this library target using &amp;lt;code&amp;gt;target_include_directories&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Link the &amp;lt;code&amp;gt;sensor_driver&amp;lt;/code&amp;gt; library to your main executable.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Verification:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; inside the build folder. You must see it compile &amp;lt;code&amp;gt;libsensor_driver.a&amp;lt;/code&amp;gt; first, and then link it to the main executable.&lt;br /&gt;
&lt;br /&gt;
=== Challenge 4: Third-Party Git Dependencies (Estimated time: 30 mins) ===&lt;br /&gt;
Our IoT node needs to transmit its data as a JSON payload, but writing a JSON parser from scratch is inefficient. &lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
# Use CMake&amp;#039;s &amp;lt;code&amp;gt;FetchContent&amp;lt;/code&amp;gt; module to download the popular &amp;quot;Nlohmann JSON&amp;quot; library directly from GitHub.&lt;br /&gt;
#* Repo: &amp;lt;code&amp;gt;https://github.com/nlohmann/json.git&amp;lt;/code&amp;gt;&lt;br /&gt;
#* Tag: &amp;lt;code&amp;gt;v3.11.2&amp;lt;/code&amp;gt;&lt;br /&gt;
# Link the imported target (&amp;lt;code&amp;gt;nlohmann_json::nlohmann_json&amp;lt;/code&amp;gt;) to your main executable.&lt;br /&gt;
# Modify &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; to include &amp;lt;code&amp;gt;&amp;lt;nlohmann/json.hpp&amp;gt;&amp;lt;/code&amp;gt;. Serialize your &amp;lt;code&amp;gt;SensorData&amp;lt;/code&amp;gt; into a JSON object and print it to the console using &amp;lt;code&amp;gt;.dump(4)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Verification:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
Running your executable should print a perfectly formatted, multi-line JSON string representing your sensor data. Check &amp;lt;code&amp;gt;build/_deps/&amp;lt;/code&amp;gt; to see the downloaded source code.&lt;br /&gt;
&lt;br /&gt;
== Lab Evaluation ==&lt;br /&gt;
To receive full credit, submit the following elements on Moodle:&lt;br /&gt;
# Final version of the Makefile.&lt;br /&gt;
# Final version of the CMakeLists.txt.&lt;br /&gt;
# Screenshot of the console output of your executable printing the JSON payload.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_3&amp;diff=8291</id>
		<title>SDPT Lab 3</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_3&amp;diff=8291"/>
		<updated>2026-03-15T22:46:16Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Lab 3: Build Automation - Makefiles and Modern CMake =&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
In professional embedded development, clicking a &amp;quot;Build&amp;quot; button in an IDE is a luxury you rarely have. When working with Embedded Linux, RTOS environments, or CI/CD pipelines, you must define exactly how your source code is translated into machine code. &lt;br /&gt;
&lt;br /&gt;
This lab transitions you from manual terminal commands to scalable build automation. &lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
* Understand the C++ compilation pipeline (Preprocessing $\rightarrow$ Compilation $\rightarrow$ Linking).&lt;br /&gt;
* Master GNU Make: pattern rules, automatic variables, and header dependency generation.&lt;br /&gt;
* Master Modern CMake: out-of-source builds, targets, and static libraries.&lt;br /&gt;
* Integrate remote third-party libraries using CMake &amp;lt;code&amp;gt;FetchContent&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Part 1: Theoretical Reference ==&lt;br /&gt;
&amp;#039;&amp;#039;Use this section as a reference manual to complete the tasks in Part 2.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 1.1 GNU Make Fundamentals ===&lt;br /&gt;
Make tracks file modification timestamps to avoid recompiling code that hasn&amp;#039;t changed. A &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; consists of rules:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;make&amp;quot;&amp;gt;&lt;br /&gt;
target: dependencies&lt;br /&gt;
&amp;lt;TAB&amp;gt; command&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;(Note: Makefiles strictly require a real TAB character for indentation, not spaces!)&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Automatic Variables:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Make provides shortcuts to avoid typing duplicate filenames:&lt;br /&gt;
* &amp;lt;code&amp;gt;$@&amp;lt;/code&amp;gt; : The target filename.&lt;br /&gt;
* &amp;lt;code&amp;gt;$&amp;lt;&amp;lt;/code&amp;gt; : The first dependency.&lt;br /&gt;
* &amp;lt;code&amp;gt;$^&amp;lt;/code&amp;gt; : All dependencies (space-separated).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Pattern Rules:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Instead of writing a rule for every file, use a pattern template:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;make&amp;quot;&amp;gt;&lt;br /&gt;
%.o: %.cpp&lt;br /&gt;
	$(CXX) $(CXXFLAGS) -c $&amp;lt; -o $@&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;GCC Auto-Dependencies (The Header Problem):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
If you change a &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; file, Make won&amp;#039;t normally detect it because object files depend on &amp;lt;code&amp;gt;.cpp&amp;lt;/code&amp;gt; files. We ask GCC to generate dependency (&amp;lt;code&amp;gt;.d&amp;lt;/code&amp;gt;) files for us:&lt;br /&gt;
* Add &amp;lt;code&amp;gt;-MMD -MP&amp;lt;/code&amp;gt; to your &amp;lt;code&amp;gt;CXXFLAGS&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Include the generated files at the bottom of your Makefile using: &amp;lt;code&amp;gt;-include $(DEPS)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1.2 Modern CMake Fundamentals ===&lt;br /&gt;
CMake is a meta-build system. It generates Makefiles (or Ninja files, or Visual Studio solutions) based on a high-level &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt; script. Modern CMake is &amp;quot;Target-Based&amp;quot;—you define targets (executables/libraries) and attach properties to them.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Core Commands:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cmake&amp;quot;&amp;gt;&lt;br /&gt;
cmake_minimum_required(VERSION 3.10)&lt;br /&gt;
project(MyProject CXX)&lt;br /&gt;
&lt;br /&gt;
# Build an executable from source&lt;br /&gt;
add_executable(my_app main.cpp)&lt;br /&gt;
&lt;br /&gt;
# Build a static library (.a archive)&lt;br /&gt;
add_library(my_driver STATIC driver.cpp)&lt;br /&gt;
&lt;br /&gt;
# Define where a target should look for header files&lt;br /&gt;
target_include_directories(my_driver PUBLIC include/)&lt;br /&gt;
&lt;br /&gt;
# Link a library to an executable&lt;br /&gt;
target_link_libraries(my_app PRIVATE my_driver)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Out-of-Source Builds:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Never pollute your source directory with binaries. Always build in a separate folder:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mkdir build &amp;amp;&amp;amp; cd build&lt;br /&gt;
cmake ..&lt;br /&gt;
make&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Fetching External Libraries:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
CMake can download libraries directly from Git during the configuration phase:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cmake&amp;quot;&amp;gt;&lt;br /&gt;
include(FetchContent)&lt;br /&gt;
FetchContent_Declare(&lt;br /&gt;
  json_lib&lt;br /&gt;
  GIT_REPOSITORY https://github.com/nlohmann/json.git&lt;br /&gt;
  GIT_TAG        v3.11.2&lt;br /&gt;
)&lt;br /&gt;
FetchContent_MakeAvailable(json_lib)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1.3 Useful Resources ===&lt;br /&gt;
* [https://www.gnu.org/software/make/manual/make.html GNU Make Manual]&lt;br /&gt;
* [https://cmake.org/cmake/help/latest/ CMake Official Documentation]&lt;br /&gt;
&lt;br /&gt;
== Part 2: The Challenges ==&lt;br /&gt;
&lt;br /&gt;
=== Setup: The Raw Materials ===&lt;br /&gt;
Create a new directory for this lab (&amp;lt;code&amp;gt;sdpt-lab3&amp;lt;/code&amp;gt;). Inside, create an &amp;lt;code&amp;gt;include/&amp;lt;/code&amp;gt; directory and a &amp;lt;code&amp;gt;src/&amp;lt;/code&amp;gt; directory. Populate them with the following three files to simulate an IoT sensor node.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;include/sensor.h&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#pragma once&lt;br /&gt;
&lt;br /&gt;
struct SensorData {&lt;br /&gt;
    int temperature;&lt;br /&gt;
    int humidity;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void init_sensor();&lt;br /&gt;
SensorData read_sensor();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;src/sensor.cpp&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
#include &amp;quot;../include/sensor.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void init_sensor() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;[Hardware] I2C Sensor Initialized.&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
SensorData read_sensor() {&lt;br /&gt;
    return {24, 60};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;src/main.cpp&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
#include &amp;quot;../include/sensor.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Starting IoT Node...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    init_sensor();&lt;br /&gt;
    &lt;br /&gt;
    SensorData data = read_sensor();&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Temp: &amp;quot; &amp;lt;&amp;lt; data.temperature &amp;lt;&amp;lt; &amp;quot;C, Hum: &amp;quot; &amp;lt;&amp;lt; data.humidity &amp;lt;&amp;lt; &amp;quot;%&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Challenge 1: The Scalable Makefile (Estimated time: 25 mins) ===&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039; Write a &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; in the root directory that compiles these files into an executable named &amp;lt;code&amp;gt;iot_node.bin&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Do &amp;#039;&amp;#039;&amp;#039;not&amp;#039;&amp;#039;&amp;#039; hardcode the &amp;lt;code&amp;gt;.cpp&amp;lt;/code&amp;gt; file names. Use the &amp;lt;code&amp;gt;wildcard&amp;lt;/code&amp;gt; function to find them dynamically.&lt;br /&gt;
* Use variables for the compiler (&amp;lt;code&amp;gt;CXX&amp;lt;/code&amp;gt;) and flags (&amp;lt;code&amp;gt;CXXFLAGS&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Use Pattern Rules and Automatic Variables to compile &amp;lt;code&amp;gt;.cpp&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;.o&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Implement GCC header dependency tracking (&amp;lt;code&amp;gt;-MMD -MP&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Verification:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. It should compile successfully. &lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; again immediately. It should say &amp;quot;Nothing to be done&amp;quot;.&lt;br /&gt;
# Open &amp;lt;code&amp;gt;include/sensor.h&amp;lt;/code&amp;gt; and add a dummy integer to the &amp;lt;code&amp;gt;SensorData&amp;lt;/code&amp;gt; struct. Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; again. It MUST recompile both &amp;lt;code&amp;gt;.cpp&amp;lt;/code&amp;gt; files automatically. If it doesn&amp;#039;t, your dependency tracking is broken.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Challenge 2: Migrating to CMake (Estimated time: 20 mins) ===&lt;br /&gt;
Makefiles are not cross-platform. We are moving to CMake.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
# Run &amp;lt;code&amp;gt;make clean&amp;lt;/code&amp;gt; (or manually delete all generated &amp;lt;code&amp;gt;.o&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.d&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;.bin&amp;lt;/code&amp;gt; files).&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt; file to build the exact same executable.&lt;br /&gt;
# Set the C++ standard to C++14.&lt;br /&gt;
# Perform an &amp;#039;&amp;#039;&amp;#039;Out-of-Source build&amp;#039;&amp;#039;&amp;#039; using a &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Verification:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
Your root directory should contain only your source files and the &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt;. Inside the &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory, running &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; should yield the executable.&lt;br /&gt;
&lt;br /&gt;
=== Challenge 3: Modular Architecture (Estimated time: 25 mins) ===&lt;br /&gt;
Dumping all source files into a single executable is bad practice. Hardware drivers should be isolated into static libraries.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039; Modify your &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Remove &amp;lt;code&amp;gt;src/sensor.cpp&amp;lt;/code&amp;gt; from your executable target.&lt;br /&gt;
# Create a new STATIC library target named &amp;lt;code&amp;gt;sensor_driver&amp;lt;/code&amp;gt; from &amp;lt;code&amp;gt;src/sensor.cpp&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Attach the &amp;lt;code&amp;gt;include/&amp;lt;/code&amp;gt; directory to this library target using &amp;lt;code&amp;gt;target_include_directories&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Link the &amp;lt;code&amp;gt;sensor_driver&amp;lt;/code&amp;gt; library to your main executable.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Verification:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; inside the build folder. You must see it compile &amp;lt;code&amp;gt;libsensor_driver.a&amp;lt;/code&amp;gt; first, and then link it to the main executable.&lt;br /&gt;
&lt;br /&gt;
=== Challenge 4: Third-Party Git Dependencies (Estimated time: 30 mins) ===&lt;br /&gt;
Our IoT node needs to transmit its data as a JSON payload, but writing a JSON parser from scratch is inefficient. &lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
# Use CMake&amp;#039;s &amp;lt;code&amp;gt;FetchContent&amp;lt;/code&amp;gt; module to download the popular &amp;quot;Nlohmann JSON&amp;quot; library directly from GitHub.&lt;br /&gt;
#* Repo: &amp;lt;code&amp;gt;https://github.com/nlohmann/json.git&amp;lt;/code&amp;gt;&lt;br /&gt;
#* Tag: &amp;lt;code&amp;gt;v3.11.2&amp;lt;/code&amp;gt;&lt;br /&gt;
# Link the imported target (&amp;lt;code&amp;gt;nlohmann_json::nlohmann_json&amp;lt;/code&amp;gt;) to your main executable.&lt;br /&gt;
# Modify &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; to include &amp;lt;code&amp;gt;&amp;lt;nlohmann/json.hpp&amp;gt;&amp;lt;/code&amp;gt;. Serialize your &amp;lt;code&amp;gt;SensorData&amp;lt;/code&amp;gt; into a JSON object and print it to the console using &amp;lt;code&amp;gt;.dump(4)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Verification:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
Running your executable should print a perfectly formatted, multi-line JSON string representing your sensor data. Check &amp;lt;code&amp;gt;build/_deps/&amp;lt;/code&amp;gt; to see the downloaded source code.&lt;br /&gt;
&lt;br /&gt;
== Lab Evaluation ==&lt;br /&gt;
To receive full credit, call the professor/TA to your workstation and demonstrate:&lt;br /&gt;
# The GCC dependency tracking working in Challenge 1 (changing a header triggers a recompile).&lt;br /&gt;
# The clean root directory, proving an Out-of-Source build.&lt;br /&gt;
# The &amp;lt;code&amp;gt;libsensor_driver.a&amp;lt;/code&amp;gt; static library file inside your build directory.&lt;br /&gt;
# The console output of your executable printing the JSON payload.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_3&amp;diff=8290</id>
		<title>SDPT Lab 3</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_3&amp;diff=8290"/>
		<updated>2026-03-15T22:43:20Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Lab 3: Build Automation - Makefiles and Modern CMake =&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
In professional embedded development, clicking a &amp;quot;Build&amp;quot; button in an IDE is a luxury you rarely have. When working with Embedded Linux, RTOS environments, or CI/CD pipelines, you must define exactly how your source code is translated into machine code. &lt;br /&gt;
&lt;br /&gt;
This lab transitions you from manual terminal commands to scalable build automation. &lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
* Understand the C++ compilation pipeline (Preprocessing $\rightarrow$ Compilation $\rightarrow$ Linking).&lt;br /&gt;
* Master GNU Make: pattern rules, automatic variables, and header dependency generation.&lt;br /&gt;
* Master Modern CMake: out-of-source builds, targets, and static libraries.&lt;br /&gt;
* Integrate remote third-party libraries using CMake &amp;lt;code&amp;gt;FetchContent&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 1: Theoretical Reference ==&lt;br /&gt;
&amp;#039;&amp;#039;Use this section as a reference manual to complete the tasks in Part 2.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 1.1 GNU Make Fundamentals ===&lt;br /&gt;
Make tracks file modification timestamps to avoid recompiling code that hasn&amp;#039;t changed. A &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; consists of rules:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;make&amp;quot;&amp;gt;&lt;br /&gt;
target: dependencies&lt;br /&gt;
&amp;lt;TAB&amp;gt; command&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;(Note: Makefiles strictly require a real TAB character for indentation, not spaces!)&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Automatic Variables:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Make provides shortcuts to avoid typing duplicate filenames:&lt;br /&gt;
* &amp;lt;code&amp;gt;$@&amp;lt;/code&amp;gt; : The target filename.&lt;br /&gt;
* &amp;lt;code&amp;gt;$&amp;lt;&amp;lt;/code&amp;gt; : The first dependency.&lt;br /&gt;
* &amp;lt;code&amp;gt;$^&amp;lt;/code&amp;gt; : All dependencies (space-separated).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Pattern Rules:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Instead of writing a rule for every file, use a pattern template:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;make&amp;quot;&amp;gt;&lt;br /&gt;
%.o: %.cpp&lt;br /&gt;
	$(CXX) $(CXXFLAGS) -c $&amp;lt; -o $@&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;GCC Auto-Dependencies (The Header Problem):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
If you change a &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; file, Make won&amp;#039;t normally detect it because object files depend on &amp;lt;code&amp;gt;.cpp&amp;lt;/code&amp;gt; files. We ask GCC to generate dependency (&amp;lt;code&amp;gt;.d&amp;lt;/code&amp;gt;) files for us:&lt;br /&gt;
* Add &amp;lt;code&amp;gt;-MMD -MP&amp;lt;/code&amp;gt; to your &amp;lt;code&amp;gt;CXXFLAGS&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Include the generated files at the bottom of your Makefile using: &amp;lt;code&amp;gt;-include $(DEPS)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1.2 Modern CMake Fundamentals ===&lt;br /&gt;
CMake is a meta-build system. It generates Makefiles (or Ninja files, or Visual Studio solutions) based on a high-level &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt; script. Modern CMake is &amp;quot;Target-Based&amp;quot;—you define targets (executables/libraries) and attach properties to them.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Core Commands:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cmake&amp;quot;&amp;gt;&lt;br /&gt;
cmake_minimum_required(VERSION 3.10)&lt;br /&gt;
project(MyProject CXX)&lt;br /&gt;
&lt;br /&gt;
# Build an executable from source&lt;br /&gt;
add_executable(my_app main.cpp)&lt;br /&gt;
&lt;br /&gt;
# Build a static library (.a archive)&lt;br /&gt;
add_library(my_driver STATIC driver.cpp)&lt;br /&gt;
&lt;br /&gt;
# Define where a target should look for header files&lt;br /&gt;
target_include_directories(my_driver PUBLIC include/)&lt;br /&gt;
&lt;br /&gt;
# Link a library to an executable&lt;br /&gt;
target_link_libraries(my_app PRIVATE my_driver)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Out-of-Source Builds:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
Never pollute your source directory with binaries. Always build in a separate folder:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mkdir build &amp;amp;&amp;amp; cd build&lt;br /&gt;
cmake ..&lt;br /&gt;
make&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Fetching External Libraries:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
CMake can download libraries directly from Git during the configuration phase:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cmake&amp;quot;&amp;gt;&lt;br /&gt;
include(FetchContent)&lt;br /&gt;
FetchContent_Declare(&lt;br /&gt;
  json_lib&lt;br /&gt;
  GIT_REPOSITORY https://github.com/nlohmann/json.git&lt;br /&gt;
  GIT_TAG        v3.11.2&lt;br /&gt;
)&lt;br /&gt;
FetchContent_MakeAvailable(json_lib)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 1.3 Useful Resources ===&lt;br /&gt;
* [https://www.gnu.org/software/make/manual/make.html GNU Make Manual]&lt;br /&gt;
* [https://cmake.org/cmake/help/latest/ CMake Official Documentation]&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 2: The Challenges ==&lt;br /&gt;
&lt;br /&gt;
=== Setup: The Raw Materials ===&lt;br /&gt;
Create a new directory for this lab (&amp;lt;code&amp;gt;sdpt-lab3&amp;lt;/code&amp;gt;). Inside, create an &amp;lt;code&amp;gt;include/&amp;lt;/code&amp;gt; directory and a &amp;lt;code&amp;gt;src/&amp;lt;/code&amp;gt; directory. Populate them with the following three files to simulate an IoT sensor node.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;include/sensor.h&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#pragma once&lt;br /&gt;
&lt;br /&gt;
struct SensorData {&lt;br /&gt;
    int temperature;&lt;br /&gt;
    int humidity;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void init_sensor();&lt;br /&gt;
SensorData read_sensor();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;src/sensor.cpp&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
#include &amp;quot;../include/sensor.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void init_sensor() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;[Hardware] I2C Sensor Initialized.&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
SensorData read_sensor() {&lt;br /&gt;
    return {24, 60};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;src/main.cpp&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
#include &amp;quot;../include/sensor.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Starting IoT Node...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    init_sensor();&lt;br /&gt;
    &lt;br /&gt;
    SensorData data = read_sensor();&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Temp: &amp;quot; &amp;lt;&amp;lt; data.temperature &amp;lt;&amp;lt; &amp;quot;C, Hum: &amp;quot; &amp;lt;&amp;lt; data.humidity &amp;lt;&amp;lt; &amp;quot;%&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
=== Challenge 1: The Scalable Makefile (Estimated time: 25 mins) ===&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039; Write a &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; in the root directory that compiles these files into an executable named &amp;lt;code&amp;gt;iot_node.bin&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Do &amp;#039;&amp;#039;&amp;#039;not&amp;#039;&amp;#039;&amp;#039; hardcode the &amp;lt;code&amp;gt;.cpp&amp;lt;/code&amp;gt; file names. Use the &amp;lt;code&amp;gt;wildcard&amp;lt;/code&amp;gt; function to find them dynamically.&lt;br /&gt;
* Use variables for the compiler (&amp;lt;code&amp;gt;CXX&amp;lt;/code&amp;gt;) and flags (&amp;lt;code&amp;gt;CXXFLAGS&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Use Pattern Rules and Automatic Variables to compile &amp;lt;code&amp;gt;.cpp&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;.o&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Implement GCC header dependency tracking (&amp;lt;code&amp;gt;-MMD -MP&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Verification:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. It should compile successfully. &lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; again immediately. It should say &amp;quot;Nothing to be done&amp;quot;.&lt;br /&gt;
# Open &amp;lt;code&amp;gt;include/sensor.h&amp;lt;/code&amp;gt; and add a dummy integer to the &amp;lt;code&amp;gt;SensorData&amp;lt;/code&amp;gt; struct. Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; again. It MUST recompile both &amp;lt;code&amp;gt;.cpp&amp;lt;/code&amp;gt; files automatically. If it doesn&amp;#039;t, your dependency tracking is broken.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
=== Challenge 2: Migrating to CMake (Estimated time: 20 mins) ===&lt;br /&gt;
Makefiles are not cross-platform. We are moving to CMake.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
# Run &amp;lt;code&amp;gt;make clean&amp;lt;/code&amp;gt; (or manually delete all generated &amp;lt;code&amp;gt;.o&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.d&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;.bin&amp;lt;/code&amp;gt; files).&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt; file to build the exact same executable.&lt;br /&gt;
# Set the C++ standard to C++14.&lt;br /&gt;
# Perform an &amp;#039;&amp;#039;&amp;#039;Out-of-Source build&amp;#039;&amp;#039;&amp;#039; using a &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Verification:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
Your root directory should contain only your source files and the &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt;. Inside the &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory, running &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; should yield the executable.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
=== Challenge 3: Modular Architecture (Estimated time: 25 mins) ===&lt;br /&gt;
Dumping all source files into a single executable is bad practice. Hardware drivers should be isolated into static libraries.&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039; Modify your &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Remove &amp;lt;code&amp;gt;src/sensor.cpp&amp;lt;/code&amp;gt; from your executable target.&lt;br /&gt;
# Create a new STATIC library target named &amp;lt;code&amp;gt;sensor_driver&amp;lt;/code&amp;gt; from &amp;lt;code&amp;gt;src/sensor.cpp&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Attach the &amp;lt;code&amp;gt;include/&amp;lt;/code&amp;gt; directory to this library target using &amp;lt;code&amp;gt;target_include_directories&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Link the &amp;lt;code&amp;gt;sensor_driver&amp;lt;/code&amp;gt; library to your main executable.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Verification:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; inside the build folder. You must see it compile &amp;lt;code&amp;gt;libsensor_driver.a&amp;lt;/code&amp;gt; first, and then link it to the main executable.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
=== Challenge 4: Third-Party Git Dependencies (Estimated time: 30 mins) ===&lt;br /&gt;
Our IoT node needs to transmit its data as a JSON payload, but writing a JSON parser from scratch is inefficient. &lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Your Task:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
# Use CMake&amp;#039;s &amp;lt;code&amp;gt;FetchContent&amp;lt;/code&amp;gt; module to download the popular &amp;quot;Nlohmann JSON&amp;quot; library directly from GitHub.&lt;br /&gt;
#* Repo: &amp;lt;code&amp;gt;https://github.com/nlohmann/json.git&amp;lt;/code&amp;gt;&lt;br /&gt;
#* Tag: &amp;lt;code&amp;gt;v3.11.2&amp;lt;/code&amp;gt;&lt;br /&gt;
# Link the imported target (&amp;lt;code&amp;gt;nlohmann_json::nlohmann_json&amp;lt;/code&amp;gt;) to your main executable.&lt;br /&gt;
# Modify &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; to include &amp;lt;code&amp;gt;&amp;lt;nlohmann/json.hpp&amp;gt;&amp;lt;/code&amp;gt;. Serialize your &amp;lt;code&amp;gt;SensorData&amp;lt;/code&amp;gt; into a JSON object and print it to the console using &amp;lt;code&amp;gt;.dump(4)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Verification:&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
Running your executable should print a perfectly formatted, multi-line JSON string representing your sensor data. Check &amp;lt;code&amp;gt;build/_deps/&amp;lt;/code&amp;gt; to see the downloaded source code.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Lab Evaluation ==&lt;br /&gt;
To receive full credit, call the professor/TA to your workstation and demonstrate:&lt;br /&gt;
# The GCC dependency tracking working in Challenge 1 (changing a header triggers a recompile).&lt;br /&gt;
# The clean root directory, proving an Out-of-Source build.&lt;br /&gt;
# The &amp;lt;code&amp;gt;libsensor_driver.a&amp;lt;/code&amp;gt; static library file inside your build directory.&lt;br /&gt;
# The console output of your executable printing the JSON payload.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_3&amp;diff=8289</id>
		<title>SDPT Lab 3</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_3&amp;diff=8289"/>
		<updated>2026-03-15T22:37:31Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: Pagină nouă: = Lab 3: Build Systems - From GNU Make to Modern CMake =  == Introduction == In Week 2, we solved the human collaboration problem using Git. Today, we solve the compilation scaling...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Lab 3: Build Systems - From GNU Make to Modern CMake =&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
In Week 2, we solved the human collaboration problem using Git. Today, we solve the compilation scaling problem. &lt;br /&gt;
&lt;br /&gt;
As embedded projects grow from a single file to hundreds of files with external dependencies (like cryptography or networking libraries), clicking a &amp;quot;Build&amp;quot; button in an IDE or typing &amp;lt;code&amp;gt;g++ main.cpp&amp;lt;/code&amp;gt; in the terminal is no longer viable. By the end of this 2-hour lab, you will have:&lt;br /&gt;
# Written a scalable GNU Makefile using pattern rules and automatic variables.&lt;br /&gt;
# Solved the &amp;quot;Header Dependency Problem&amp;quot; using GCC&amp;#039;s &amp;lt;code&amp;gt;-MMD&amp;lt;/code&amp;gt; flags.&lt;br /&gt;
# Migrated the project to Modern CMake.&lt;br /&gt;
# Enforced clean &amp;quot;Out-of-Source&amp;quot; builds.&lt;br /&gt;
# Built a static hardware driver library and linked it to an executable.&lt;br /&gt;
# Automatically downloaded and linked a 3rd-party library directly from GitHub using CMake&amp;#039;s &amp;lt;code&amp;gt;FetchContent&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Requirement:&amp;#039;&amp;#039;&amp;#039; You may work individually or with your partner from last week.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 1: Project Setup and The GNU Make Baseline (30 Minutes) ==&lt;br /&gt;
First, we need some source code to compile. We will simulate an IoT sensor node.&lt;br /&gt;
&lt;br /&gt;
=== 1. Create the Project Workspace ===&lt;br /&gt;
Open your terminal and create a new directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir sdpt-lab3-builds&lt;br /&gt;
cd sdpt-lab3-builds&lt;br /&gt;
mkdir src include&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. Create the Source Files ===&lt;br /&gt;
Create a header file &amp;lt;code&amp;gt;include/sensor.h&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef SENSOR_H&lt;br /&gt;
#define SENSOR_H&lt;br /&gt;
&lt;br /&gt;
struct SensorData {&lt;br /&gt;
    int temperature;&lt;br /&gt;
    int humidity;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void init_sensor();&lt;br /&gt;
SensorData read_sensor();&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create the implementation file &amp;lt;code&amp;gt;src/sensor.cpp&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
#include &amp;quot;../include/sensor.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void init_sensor() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;[Hardware] I2C Sensor Initialized.&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
SensorData read_sensor() {&lt;br /&gt;
    SensorData data;&lt;br /&gt;
    data.temperature = 24;&lt;br /&gt;
    data.humidity = 60;&lt;br /&gt;
    return data;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create the main application &amp;lt;code&amp;gt;src/main.cpp&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
#include &amp;quot;../include/sensor.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Starting IoT Node...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    init_sensor();&lt;br /&gt;
    &lt;br /&gt;
    SensorData current_data = read_sensor();&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Temp: &amp;quot; &amp;lt;&amp;lt; current_data.temperature &amp;lt;&amp;lt; &amp;quot;C, Hum: &amp;quot; &amp;lt;&amp;lt; current_data.humidity &amp;lt;&amp;lt; &amp;quot;%&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 3. Write the Scalable Makefile ===&lt;br /&gt;
In the root directory (&amp;lt;code&amp;gt;sdpt-lab3-builds/&amp;lt;/code&amp;gt;), create a file named exactly &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt;. &lt;br /&gt;
&amp;#039;&amp;#039;Warning: You MUST use an actual TAB character for the indented lines, not spaces!&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CXX = g++&lt;br /&gt;
CXXFLAGS = -Wall -Wextra -O2 -MMD -MP&lt;br /&gt;
TARGET = firmware.bin&lt;br /&gt;
&lt;br /&gt;
# Dynamically find all .cpp files in the src/ directory&lt;br /&gt;
SRCS = $(wildcard src/*.cpp)&lt;br /&gt;
&lt;br /&gt;
# String substitution: convert .cpp list to .o list&lt;br /&gt;
OBJS = $(SRCS:.cpp=.o)&lt;br /&gt;
&lt;br /&gt;
# Create a list of .d (dependency) files&lt;br /&gt;
DEPS = $(OBJS:.o=.d)&lt;br /&gt;
&lt;br /&gt;
# Default rule&lt;br /&gt;
all: $(TARGET)&lt;br /&gt;
&lt;br /&gt;
# Linker rule using automatic variables ($^ = all dependencies, $@ = target)&lt;br /&gt;
$(TARGET): $(OBJS)&lt;br /&gt;
	$(CXX) $^ -o $@&lt;br /&gt;
&lt;br /&gt;
# Pattern rule to compile any .cpp into a .o file ($&amp;lt; = first dependency)&lt;br /&gt;
%.o: %.cpp&lt;br /&gt;
	$(CXX) $(CXXFLAGS) -c $&amp;lt; -o $@&lt;br /&gt;
&lt;br /&gt;
# Clean rule to remove binaries&lt;br /&gt;
clean:&lt;br /&gt;
	rm -f $(OBJS) $(DEPS) $(TARGET)&lt;br /&gt;
&lt;br /&gt;
# Include the auto-generated GCC dependencies&lt;br /&gt;
-include $(DEPS)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 4. Test and Inspect the Build ===&lt;br /&gt;
Run the build:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
make&lt;br /&gt;
./firmware.bin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, look inside your &amp;lt;code&amp;gt;src/&amp;lt;/code&amp;gt; folder. Run &amp;lt;code&amp;gt;ls src/&amp;lt;/code&amp;gt;. &lt;br /&gt;
Notice the &amp;lt;code&amp;gt;.d&amp;lt;/code&amp;gt; files? Open &amp;lt;code&amp;gt;src/main.d&amp;lt;/code&amp;gt; in a text editor. You will see that GCC automatically wrote a Makefile rule proving that &amp;lt;code&amp;gt;main.o&amp;lt;/code&amp;gt; depends on &amp;lt;code&amp;gt;sensor.h&amp;lt;/code&amp;gt;. This is how Make knows to recompile &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; if you only change the header file!&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 2: Migrating to Modern CMake (30 Minutes) ==&lt;br /&gt;
Makefiles are great, but they leave &amp;lt;code&amp;gt;.o&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;.d&amp;lt;/code&amp;gt; files scattered all over our source code, and they are not cross-platform. Let&amp;#039;s upgrade.&lt;br /&gt;
&lt;br /&gt;
=== 1. Clean up the Make artifacts ===&lt;br /&gt;
Run the clean rule to delete all the generated binaries from Part 1.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
make clean&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. Write the CMakeLists.txt ===&lt;br /&gt;
In the root directory, create a file named &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cmake_minimum_required(VERSION 3.10)&lt;br /&gt;
project(IoTNode CXX)&lt;br /&gt;
&lt;br /&gt;
set(CMAKE_CXX_STANDARD 14)&lt;br /&gt;
set(CMAKE_CXX_STANDARD_REQUIRED ON)&lt;br /&gt;
&lt;br /&gt;
# Define the executable and its source files&lt;br /&gt;
add_executable(firmware src/main.cpp src/sensor.cpp)&lt;br /&gt;
&lt;br /&gt;
# Tell CMake where to look for header files&lt;br /&gt;
target_include_directories(firmware PRIVATE include/)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 3. The Out-of-Source Build ===&lt;br /&gt;
We will never compile in the root directory again. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir build&lt;br /&gt;
cd build&lt;br /&gt;
&lt;br /&gt;
# Tell CMake to read the parent directory and generate the build system&lt;br /&gt;
cmake ..&lt;br /&gt;
&lt;br /&gt;
# Execute the build&lt;br /&gt;
make&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Run your program: &amp;lt;code&amp;gt;./firmware&amp;lt;/code&amp;gt;. Notice that your &amp;lt;code&amp;gt;src/&amp;lt;/code&amp;gt; directory is completely clean. All binaries are safely isolated inside the &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; folder.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 3: Modular Architecture (Static Libraries) (30 Minutes) ==&lt;br /&gt;
In professional embedded development, we don&amp;#039;t dump all source files into the executable. We build independent, reusable Static Libraries (&amp;lt;code&amp;gt;.a&amp;lt;/code&amp;gt; files) for hardware drivers.&lt;br /&gt;
&lt;br /&gt;
=== 1. Refactor CMakeLists.txt ===&lt;br /&gt;
Go back to your root directory and open &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt;. Rewrite it to decouple the sensor driver from the main application:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cmake_minimum_required(VERSION 3.10)&lt;br /&gt;
project(IoTNode CXX)&lt;br /&gt;
&lt;br /&gt;
set(CMAKE_CXX_STANDARD 14)&lt;br /&gt;
&lt;br /&gt;
# 1. Build the sensor driver as a STATIC library&lt;br /&gt;
add_library(sensor_lib STATIC src/sensor.cpp)&lt;br /&gt;
&lt;br /&gt;
# 2. Attach the include directory to the library (PUBLIC means anyone who links this library gets the headers too)&lt;br /&gt;
target_include_directories(sensor_lib PUBLIC include/)&lt;br /&gt;
&lt;br /&gt;
# 3. Build the main executable (Notice we removed sensor.cpp!)&lt;br /&gt;
add_executable(firmware src/main.cpp)&lt;br /&gt;
&lt;br /&gt;
# 4. Link the library to the executable&lt;br /&gt;
target_link_libraries(firmware PRIVATE sensor_lib)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. Rebuild and Verify ===&lt;br /&gt;
Go into your &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory and just run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; (CMake automatically detects the changes to CMakeLists.txt and regenerates everything).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd build&lt;br /&gt;
make&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Look at the terminal output. You should see it building &amp;lt;code&amp;gt;libsensor_lib.a&amp;lt;/code&amp;gt; first, and then linking it to &amp;lt;code&amp;gt;firmware&amp;lt;/code&amp;gt;. Run &amp;lt;code&amp;gt;ls -l&amp;lt;/code&amp;gt; to verify the &amp;lt;code&amp;gt;.a&amp;lt;/code&amp;gt; archive exists.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 4: Remote 3rd-Party Dependencies (30 Minutes) ==&lt;br /&gt;
Our IoT node generates data, but we need to format it as JSON to send it over the network. Writing a JSON parser in C++ from scratch is a terrible idea. We will use a popular 3rd-party library (Nlohmann JSON) and import it directly from GitHub using CMake&amp;#039;s &amp;lt;code&amp;gt;FetchContent&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== 1. Fetching the Library ===&lt;br /&gt;
Open your &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt; and add the FetchContent block &amp;#039;&amp;#039;before&amp;#039;&amp;#039; your executable definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cmake_minimum_required(VERSION 3.14) # Note: Upgraded to 3.14 for FetchContent&lt;br /&gt;
project(IoTNode CXX)&lt;br /&gt;
&lt;br /&gt;
set(CMAKE_CXX_STANDARD 14)&lt;br /&gt;
&lt;br /&gt;
# --- Define local library ---&lt;br /&gt;
add_library(sensor_lib STATIC src/sensor.cpp)&lt;br /&gt;
target_include_directories(sensor_lib PUBLIC include/)&lt;br /&gt;
&lt;br /&gt;
# --- Fetch 3rd Party Library from GitHub ---&lt;br /&gt;
include(FetchContent)&lt;br /&gt;
FetchContent_Declare(&lt;br /&gt;
  json&lt;br /&gt;
  GIT_REPOSITORY https://github.com/nlohmann/json.git&lt;br /&gt;
  GIT_TAG        v3.11.2&lt;br /&gt;
)&lt;br /&gt;
FetchContent_MakeAvailable(json)&lt;br /&gt;
&lt;br /&gt;
# --- Define Executable ---&lt;br /&gt;
add_executable(firmware src/main.cpp)&lt;br /&gt;
&lt;br /&gt;
# Link BOTH our local hardware library AND the remote JSON library&lt;br /&gt;
# (The remote library exposes a target named &amp;#039;nlohmann_json::nlohmann_json&amp;#039;)&lt;br /&gt;
target_link_libraries(firmware PRIVATE sensor_lib nlohmann_json::nlohmann_json)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. Use the JSON Library in Code ===&lt;br /&gt;
Open &amp;lt;code&amp;gt;src/main.cpp&amp;lt;/code&amp;gt; and update it to serialize our sensor data:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
#include &amp;quot;../include/sensor.h&amp;quot;&lt;br /&gt;
#include &amp;lt;nlohmann/json.hpp&amp;gt; // Included from the fetched library!&lt;br /&gt;
&lt;br /&gt;
using json = nlohmann::json;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Starting IoT Node...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    init_sensor();&lt;br /&gt;
    &lt;br /&gt;
    SensorData current_data = read_sensor();&lt;br /&gt;
    &lt;br /&gt;
    // Create a JSON object and pack our data into it&lt;br /&gt;
    json payload;&lt;br /&gt;
    payload[&amp;quot;device_id&amp;quot;] = &amp;quot;RPI_NODE_01&amp;quot;;&lt;br /&gt;
    payload[&amp;quot;status&amp;quot;] = &amp;quot;active&amp;quot;;&lt;br /&gt;
    payload[&amp;quot;data&amp;quot;][&amp;quot;temperature&amp;quot;] = current_data.temperature;&lt;br /&gt;
    payload[&amp;quot;data&amp;quot;][&amp;quot;humidity&amp;quot;] = current_data.humidity;&lt;br /&gt;
    &lt;br /&gt;
    // Serialize and print the JSON string&lt;br /&gt;
    std::string network_message = payload.dump(4); // 4 spaces of indentation&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;\n--- Transmission Payload ---\n&amp;quot; &amp;lt;&amp;lt; network_message &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 3. The Final Build ===&lt;br /&gt;
Go to your &amp;lt;code&amp;gt;build/&amp;lt;/code&amp;gt; directory. Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. &lt;br /&gt;
&amp;#039;&amp;#039;Note: This build will take slightly longer because CMake is reaching out to GitHub, downloading the library, and configuring it on the fly.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Run &amp;lt;code&amp;gt;./firmware&amp;lt;/code&amp;gt;. You should see a perfectly formatted JSON payload printed to your terminal!&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Lab Deliverable ==&lt;br /&gt;
To receive full credit for this week&amp;#039;s lab, demonstrate the following to your professor or TA:&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./firmware&amp;lt;/code&amp;gt; to show the successful JSON serialization.&lt;br /&gt;
# Show your &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt; file demonstrating the &amp;lt;code&amp;gt;FetchContent&amp;lt;/code&amp;gt; block and &amp;lt;code&amp;gt;target_link_libraries&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Navigate to &amp;lt;code&amp;gt;build/_deps/json-src&amp;lt;/code&amp;gt; in your terminal to prove that CMake successfully downloaded the external repository into the out-of-source build tree.&lt;br /&gt;
# Explain the difference between the &amp;lt;code&amp;gt;PUBLIC&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;PRIVATE&amp;lt;/code&amp;gt; keywords in your CMake link step.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=Software_Development_Process_and_Testing&amp;diff=8288</id>
		<title>Software Development Process and Testing</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=Software_Development_Process_and_Testing&amp;diff=8288"/>
		<updated>2026-03-15T22:37:25Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[SDPT Lab 1]]&lt;br /&gt;
* [[SDPT Lab 2]]&lt;br /&gt;
* [[SDPT Lab 3]]&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_2&amp;diff=8282</id>
		<title>SDPT Lab 2</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_2&amp;diff=8282"/>
		<updated>2026-03-02T14:11:50Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Lab 2: Multi-Player Git, Code Reviews, and Advanced Conflict Resolution =&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
In Week 1, you learned how to drive Git in &amp;quot;single-player mode.&amp;quot; Today, we switch to &amp;quot;multi-player mode.&amp;quot; Software engineering is a team sport. When multiple engineers edit the same codebase simultaneously, collisions are inevitable, and uninterrupted work is a myth. &lt;br /&gt;
&lt;br /&gt;
By the end of this 2-hour lab, you and your partner will have:&lt;br /&gt;
# Configured a shared team repository with strict Branch Protection.&lt;br /&gt;
# Used &amp;lt;code&amp;gt;git stash&amp;lt;/code&amp;gt; to handle an emergency &amp;quot;hotfix&amp;quot; interruption.&lt;br /&gt;
# Conducted an iterative Code Review (requesting and pushing fixes).&lt;br /&gt;
# Intentionally caused a Git Merge Conflict.&lt;br /&gt;
# Resolved the conflict professionally using &amp;lt;code&amp;gt;git rebase&amp;lt;/code&amp;gt; and force-pushing.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Requirement:&amp;#039;&amp;#039;&amp;#039; Find a partner. Decide who will be &amp;#039;&amp;#039;&amp;#039;Student A (The Maintainer)&amp;#039;&amp;#039;&amp;#039; and who will be &amp;#039;&amp;#039;&amp;#039;Student B (The Developer)&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 1: Team Setup and Branch Protection (20 Minutes) ==&lt;br /&gt;
We must first create a shared workspace and establish our &amp;quot;Traffic Laws.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== 1. Create the Shared Repository (Student A) ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student A:&amp;#039;&amp;#039;&amp;#039; Log into GitLab and create a new blank project named &amp;lt;code&amp;gt;sdpt-lab2-collaboration&amp;lt;/code&amp;gt;. &lt;br /&gt;
* Uncheck &amp;quot;Initialize repository with a README&amp;quot;.&lt;br /&gt;
* On the left sidebar, go to &amp;#039;&amp;#039;&amp;#039;Manage&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Members&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Invite members&amp;#039;&amp;#039;&amp;#039;. Search for &amp;#039;&amp;#039;&amp;#039;Student B&amp;#039;&amp;#039;&amp;#039; by their university email.&lt;br /&gt;
* Assign Student B the role of &amp;#039;&amp;#039;&amp;#039;Developer&amp;#039;&amp;#039;&amp;#039; and click Invite.&lt;br /&gt;
&lt;br /&gt;
=== 2. Enforce Branch Protection (Student A) ===&lt;br /&gt;
The &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; branch is sacred. No one should be allowed to push code directly to it.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student A:&amp;#039;&amp;#039;&amp;#039; In the project sidebar, go to &amp;#039;&amp;#039;&amp;#039;Settings&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Repository&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* Expand the &amp;#039;&amp;#039;&amp;#039;Protected branches&amp;#039;&amp;#039;&amp;#039; section.&lt;br /&gt;
* Ensure the branch is set to &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;master&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Set &amp;#039;&amp;#039;&amp;#039;Allowed to merge&amp;#039;&amp;#039;&amp;#039; to: &amp;lt;code&amp;gt;Developers + Maintainers&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Set &amp;#039;&amp;#039;&amp;#039;Allowed to push and merge&amp;#039;&amp;#039;&amp;#039; to: &amp;lt;code&amp;gt;No one&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Protect&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
=== 3. Initialize the Baseline (Student A) ===&lt;br /&gt;
Student A will push the initial skeleton code.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mkdir sdpt-lab2-collaboration&lt;br /&gt;
cd sdpt-lab2-collaboration&lt;br /&gt;
git init&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void init_hardware() {&lt;br /&gt;
    // TODO: Initialize communication protocol&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Sytem Booting...&amp;quot; &amp;lt;&amp;lt; std::endl; // Notice the typo!&lt;br /&gt;
    init_hardware();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Commit and push:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git commit -m &amp;quot;Initial baseline code&amp;quot;&lt;br /&gt;
git remote add origin git@gitlab.com:&amp;lt;Student-A-Username&amp;gt;/sdpt-lab2-collaboration.git&lt;br /&gt;
git push -u origin main&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 4. Clone the Repository (Student B) ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student B:&amp;#039;&amp;#039;&amp;#039; Copy the SSH clone URL from GitLab.&lt;br /&gt;
* Clone the repository to your machine:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git clone git@gitlab.com:&amp;lt;Student-A-Username&amp;gt;/sdpt-lab2-collaboration.git&lt;br /&gt;
cd sdpt-lab2-collaboration&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 2: The Emergency Interruption &amp;amp; Stash (20 Minutes) ==&lt;br /&gt;
Student B is going to start working on a feature, but Student A (acting as the manager) will interrupt them with an urgent bug fix.&lt;br /&gt;
&lt;br /&gt;
=== 1. Start Feature Work (Student B) ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student B:&amp;#039;&amp;#039;&amp;#039; Create a branch for the I2C driver.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git checkout -b feature-i2c&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Open &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; and replace the TODO comment:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
void init_hardware() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Initializing I2C Bus on Port B...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Wait! Do not commit yet!&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 2. The Emergency (Student A) ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student A:&amp;#039;&amp;#039;&amp;#039; &amp;quot;Stop what you are doing! There is a typo in the main boot message (&amp;#039;Sytem Booting&amp;#039;). We need a hotfix immediately!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== 3. The Stash (Student B) ===&lt;br /&gt;
Student B cannot switch to the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; branch because they have uncommitted I2C changes. They must stash them.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git stash&lt;br /&gt;
git checkout main&lt;br /&gt;
git checkout -b hotfix-typo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 4. Fix the Bug (Student B) ===&lt;br /&gt;
Open &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; and fix the typo to say &amp;lt;code&amp;gt;&amp;quot;System Booting...&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git commit -m &amp;quot;Fix typo in boot message&amp;quot;&lt;br /&gt;
git push -u origin hotfix-typo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student B:&amp;#039;&amp;#039;&amp;#039; Go to GitLab, open a Merge Request for the hotfix, and assign Student A.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student A:&amp;#039;&amp;#039;&amp;#039; Review the MR, Approve it, and click &amp;#039;&amp;#039;&amp;#039;Merge&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
=== 5. Resume Work (Student B) ===&lt;br /&gt;
Student B, now that the emergency is handled, return to your feature and pop your stash.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git checkout feature-i2c&lt;br /&gt;
git stash pop&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Your I2C code has returned! Commit and push it.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git commit -m &amp;quot;Add I2C hardware initialization&amp;quot;&lt;br /&gt;
git push -u origin feature-i2c&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Open a Merge Request for &amp;lt;code&amp;gt;feature-i2c&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 3: Parallel Dev &amp;amp; Iterative Code Review (25 Minutes) ==&lt;br /&gt;
While Student B was working, Student A was supposed to be writing the SPI driver.&lt;br /&gt;
&lt;br /&gt;
=== 1. Create the Collision (Student A) ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student A:&amp;#039;&amp;#039;&amp;#039; Make sure you are on &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; and pull the latest changes (the typo fix).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git checkout main&lt;br /&gt;
git pull origin main&lt;br /&gt;
git checkout -b feature-spi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Open &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; and edit the EXACT SAME LINE that Student B edited:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
void init_hardware() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Initializing SPI Bus on Port A...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Commit, push, and open an MR.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git commit -m &amp;quot;Add SPI hardware initialization&amp;quot;&lt;br /&gt;
git push -u origin feature-spi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. The Iterative Review ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student A:&amp;#039;&amp;#039;&amp;#039; Go to Student B&amp;#039;s Merge Request (the I2C one).&lt;br /&gt;
* Do &amp;#039;&amp;#039;&amp;#039;NOT&amp;#039;&amp;#039;&amp;#039; approve it. We are going to request a change.&lt;br /&gt;
* Go to the &amp;#039;&amp;#039;&amp;#039;Changes&amp;#039;&amp;#039;&amp;#039; tab. Click the comment bubble next to the I2C line and write: &amp;#039;&amp;#039;&amp;quot;We need to specify the baud rate here. Please add &amp;#039;at 400kHz&amp;#039; to the output.&amp;quot;&amp;#039;&amp;#039; Click &amp;#039;&amp;#039;&amp;#039;Start a review&amp;#039;&amp;#039;&amp;#039; and then &amp;#039;&amp;#039;&amp;#039;Submit review&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
=== 3. Implementing the Fix (Student B) ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student B:&amp;#039;&amp;#039;&amp;#039; You received a change request. Update your code locally.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
void init_hardware() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Initializing I2C Bus on Port B at 400kHz...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git commit -m &amp;quot;Update I2C init to include baud rate per code review&amp;quot;&lt;br /&gt;
git push origin feature-i2c&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Notice that your GitLab MR automatically updates! &lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student A:&amp;#039;&amp;#039;&amp;#039; Check the MR again. The requested change is there. Click &amp;#039;&amp;#039;&amp;#039;Approve&amp;#039;&amp;#039;&amp;#039; and &amp;#039;&amp;#039;&amp;#039;Merge&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 4: The Rebase Conflict (25 Minutes) ==&lt;br /&gt;
Because Student B&amp;#039;s MR was merged first, Student A&amp;#039;s MR (SPI) is now broken. &lt;br /&gt;
&lt;br /&gt;
=== 1. Discovering the Conflict (Student A) ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student A:&amp;#039;&amp;#039;&amp;#039; Check your &amp;lt;code&amp;gt;feature-spi&amp;lt;/code&amp;gt; Merge Request on GitLab. You will see a red warning: &amp;#039;&amp;#039;&amp;#039;Merge blocked: merge conflicts must be resolved.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 2. Fetch and Rebase (Student A) ===&lt;br /&gt;
We will resolve this using the professional Trunk-Based standard: Rebasing.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Download the latest state of the remote server&lt;br /&gt;
git fetch origin&lt;br /&gt;
&lt;br /&gt;
# Replay your SPI commits on top of the newly updated main branch&lt;br /&gt;
git rebase origin/main&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Git will stop and output: &amp;lt;code&amp;gt;CONFLICT (content): Merge conflict in main.cpp.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 3. Fix the Code (Student A) ===&lt;br /&gt;
Open &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt;. You will see the Git markers. &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
void init_hardware() {&lt;br /&gt;
&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Initializing I2C Bus on Port B at 400kHz...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
=======&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Initializing SPI Bus on Port A...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Add SPI hardware initialization&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Delete the markers and combine the code so BOTH interfaces initialize:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
void init_hardware() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Initializing I2C Bus on Port B at 400kHz...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Initializing SPI Bus on Port A...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 4. Continue and Force Push (Student A) ===&lt;br /&gt;
Stage the resolved file and tell the rebase to continue.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git rebase --continue&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Because rebasing rewrites history, your local branch and the remote branch have diverged. A normal &amp;lt;code&amp;gt;git push&amp;lt;/code&amp;gt; will fail. You must force it.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push --force origin feature-spi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 5. Final Approval (Student B) ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student B:&amp;#039;&amp;#039;&amp;#039; Go to Student A&amp;#039;s MR. The conflict is gone! &lt;br /&gt;
* Review the code, click &amp;#039;&amp;#039;&amp;#039;Approve&amp;#039;&amp;#039;&amp;#039;, and click &amp;#039;&amp;#039;&amp;#039;Merge&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Lab Deliverable ==&lt;br /&gt;
To receive full credit for this week&amp;#039;s lab, call the professor or TA over and demonstrate:&lt;br /&gt;
# Your GitLab MR history showing &amp;#039;&amp;#039;&amp;#039;three&amp;#039;&amp;#039;&amp;#039; merged requests (Hotfix, I2C, SPI).&lt;br /&gt;
# Inside the I2C MR, show the comment thread where a change was requested and resolved.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;git log --graph --oneline&amp;lt;/code&amp;gt; on your terminal to prove the final history includes all features without broken code.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_2&amp;diff=8281</id>
		<title>SDPT Lab 2</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_2&amp;diff=8281"/>
		<updated>2026-03-02T14:04:49Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: Pagină nouă: = Lab 2: Multi-Player Git, Merge Requests, and Conflict Resolution =  == Introduction == In Week 1, you learned how to drive Git in &amp;quot;single-player mode.&amp;quot; You initialized a reposito...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Lab 2: Multi-Player Git, Merge Requests, and Conflict Resolution =&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
In Week 1, you learned how to drive Git in &amp;quot;single-player mode.&amp;quot; You initialized a repository, staged files, and pushed to your own remote server. &lt;br /&gt;
&lt;br /&gt;
Today, we switch to &amp;quot;multi-player mode.&amp;quot; Software engineering is a team sport. When multiple engineers edit the same codebase simultaneously, collisions are inevitable. By the end of this 2-hour lab, you and a partner will have:&lt;br /&gt;
# Configured a shared team repository.&lt;br /&gt;
# Enforced Trunk-Based Development by locking down the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; branch.&lt;br /&gt;
# Worked in parallel on feature branches.&lt;br /&gt;
# Intentionally caused a Git Merge Conflict.&lt;br /&gt;
# Resolved the conflict using Git commands and GitLab Merge Requests (MRs).&lt;br /&gt;
# Conducted a formal Code Review.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Requirement:&amp;#039;&amp;#039;&amp;#039; Find a partner. Decide who will be &amp;#039;&amp;#039;&amp;#039;Student A (The Maintainer)&amp;#039;&amp;#039;&amp;#039; and who will be &amp;#039;&amp;#039;&amp;#039;Student B (The Developer)&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 1: Team Setup and Branch Protection (20 Minutes) ==&lt;br /&gt;
We must first create a shared workspace and establish our &amp;quot;Traffic Laws&amp;quot; (Branch Protection).&lt;br /&gt;
&lt;br /&gt;
=== 1. Create the Shared Repository (Student A) ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student A:&amp;#039;&amp;#039;&amp;#039; Log into GitLab and create a new blank project named &amp;lt;code&amp;gt;sdpt-lab2-collaboration&amp;lt;/code&amp;gt;. &lt;br /&gt;
* Uncheck &amp;quot;Initialize repository with a README&amp;quot;.&lt;br /&gt;
* On the left sidebar, go to &amp;#039;&amp;#039;&amp;#039;Manage&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Members&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Invite members&amp;#039;&amp;#039;&amp;#039;. Search for &amp;#039;&amp;#039;&amp;#039;Student B&amp;#039;&amp;#039;&amp;#039; by their university email or username.&lt;br /&gt;
* Assign Student B the role of &amp;#039;&amp;#039;&amp;#039;Developer&amp;#039;&amp;#039;&amp;#039; and click Invite.&lt;br /&gt;
&lt;br /&gt;
=== 2. Enforce Branch Protection (Student A) ===&lt;br /&gt;
We are using Trunk-Based Development. The &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; branch is sacred. No one should be allowed to push broken code directly to it.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student A:&amp;#039;&amp;#039;&amp;#039; In the project sidebar, go to &amp;#039;&amp;#039;&amp;#039;Settings&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Repository&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* Expand the &amp;#039;&amp;#039;&amp;#039;Protected branches&amp;#039;&amp;#039;&amp;#039; section.&lt;br /&gt;
* Ensure the branch is set to &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;master&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Set &amp;#039;&amp;#039;&amp;#039;Allowed to merge&amp;#039;&amp;#039;&amp;#039; to: &amp;lt;code&amp;gt;Developers + Maintainers&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Set &amp;#039;&amp;#039;&amp;#039;Allowed to push and merge&amp;#039;&amp;#039;&amp;#039; to: &amp;lt;code&amp;gt;No one&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Protect&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&amp;#039;&amp;#039;(Now, the ONLY way code gets into main is through a Merge Request!)&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 3. Initialize the Baseline (Student A) ===&lt;br /&gt;
Student A will push the initial skeleton code so you both have a starting point.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Student A&amp;#039;s Terminal:&lt;br /&gt;
mkdir sdpt-lab2-collaboration&lt;br /&gt;
cd sdpt-lab2-collaboration&lt;br /&gt;
git init&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a file named &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void init_hardware() {&lt;br /&gt;
    // TODO: Initialize communication protocol&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;System Booting...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    init_hardware();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Commit and push:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git commit -m &amp;quot;Initial baseline code&amp;quot;&lt;br /&gt;
git remote add origin git@gitlab.com:&amp;lt;Student-A-Username&amp;gt;/sdpt-lab2-collaboration.git&lt;br /&gt;
git push -u origin main&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 4. Clone the Repository (Student B) ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student B:&amp;#039;&amp;#039;&amp;#039; Go to Student A&amp;#039;s GitLab project page. Copy the SSH clone URL.&lt;br /&gt;
* Open your terminal and clone the shared repository to your machine:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git clone git@gitlab.com:&amp;lt;Student-A-Username&amp;gt;/sdpt-lab2-collaboration.git&lt;br /&gt;
cd sdpt-lab2-collaboration&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 2: Parallel Realities (30 Minutes) ==&lt;br /&gt;
Both students will now create isolated branches and attempt to implement the hardware initialization logic at the exact same time.&lt;br /&gt;
&lt;br /&gt;
=== 1. Branching Out (Both Students) ===&lt;br /&gt;
Both students must run the following commands on their own machines:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Student A runs:&lt;br /&gt;
git checkout -b feature-spi-init&lt;br /&gt;
&lt;br /&gt;
# Student B runs:&lt;br /&gt;
git checkout -b feature-i2c-init&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. Writing the Code (Both Students) ===&lt;br /&gt;
Open &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; in your text editor. Find the &amp;lt;code&amp;gt;init_hardware()&amp;lt;/code&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Student A (SPI Logic):&amp;#039;&amp;#039;&amp;#039; Replace the TODO comment with this exact code:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
void init_hardware() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Initializing SPI Bus on Port A...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Student B (I2C Logic):&amp;#039;&amp;#039;&amp;#039; Replace the TODO comment with this exact code:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
void init_hardware() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Initializing I2C Bus on Port B...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 3. Commit and Push (Both Students) ===&lt;br /&gt;
Because you are on separate branches, you can both push to the server safely.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Student A:&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git commit -m &amp;quot;Add SPI hardware initialization&amp;quot;&lt;br /&gt;
git push -u origin feature-spi-init&lt;br /&gt;
&lt;br /&gt;
# Student B:&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git commit -m &amp;quot;Add I2C hardware initialization&amp;quot;&lt;br /&gt;
git push -u origin feature-i2c-init&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 4. Open Merge Requests (Both Students) ===&lt;br /&gt;
* Both students: Go to the GitLab project page. &lt;br /&gt;
* You should see a blue banner saying &amp;quot;You pushed to feature-...&amp;quot;. Click &amp;#039;&amp;#039;&amp;#039;Create merge request&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* Assign your partner as the &amp;#039;&amp;#039;&amp;#039;Reviewer&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Create merge request&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 3: The Collision &amp;amp; Code Review (30 Minutes) ==&lt;br /&gt;
Right now, both Merge Requests look green and ready to merge. Git doesn&amp;#039;t know there is a problem yet. &lt;br /&gt;
&lt;br /&gt;
=== 1. Review and Merge Student A&amp;#039;s Code ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student B:&amp;#039;&amp;#039;&amp;#039; Go to the Merge Requests tab and click on Student A&amp;#039;s MR (SPI init).&lt;br /&gt;
* Go to the &amp;#039;&amp;#039;&amp;#039;Changes&amp;#039;&amp;#039;&amp;#039; tab to review the code.&lt;br /&gt;
* Leave a comment on the line of code: &amp;quot;Looks good, SPI is the correct protocol.&amp;quot;&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Approve&amp;#039;&amp;#039;&amp;#039;, then click the green &amp;#039;&amp;#039;&amp;#039;Merge&amp;#039;&amp;#039;&amp;#039; button.&lt;br /&gt;
&lt;br /&gt;
Student A&amp;#039;s code is now officially part of the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; branch! &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 2. The Conflict Appears ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student B:&amp;#039;&amp;#039;&amp;#039; Go back to the Merge Requests list and open your own MR (I2C init).&lt;br /&gt;
* You will see a glaring error: &amp;#039;&amp;#039;&amp;#039;Merge blocked: merge conflicts must be resolved.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* &amp;#039;&amp;#039;Why did this happen?&amp;#039;&amp;#039; Both of you edited the exact same line in &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt;. Git refuses to guess whether the SPI code or the I2C code should win. A human must intervene.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 4: Resolving the Conflict (30 Minutes) ==&lt;br /&gt;
Student B must pull the new changes from the server and fix the conflict locally before they can merge.&lt;br /&gt;
&lt;br /&gt;
=== 1. Update the Local Main Branch (Student B) ===&lt;br /&gt;
Student B, your local machine does not know about Student A&amp;#039;s merged code yet.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Switch back to main&lt;br /&gt;
git checkout main&lt;br /&gt;
&lt;br /&gt;
# Download the latest changes from the server&lt;br /&gt;
git pull origin main&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. Rebase or Merge? (Student B) ===&lt;br /&gt;
Switch back to your feature branch. We need to integrate the new &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; into your feature branch. We will use a merge to resolve the conflict.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git checkout feature-i2c-init&lt;br /&gt;
git merge main&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Git will output: &amp;lt;code&amp;gt;CONFLICT (content): Merge conflict in main.cpp. Automatic merge failed.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 3. Fix the Code (Student B) ===&lt;br /&gt;
Open &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; in your text editor. Git has injected markers into your code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
void init_hardware() {&lt;br /&gt;
&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Initializing I2C Bus on Port B...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
=======&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Initializing SPI Bus on Port A...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; main&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Task:&amp;#039;&amp;#039;&amp;#039; Discuss with Student A. Decide that you actually need &amp;#039;&amp;#039;both&amp;#039;&amp;#039; protocols to initialize.&lt;br /&gt;
* Delete the Git markers (&amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;=======&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;lt;/code&amp;gt;) and combine the logic so it looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
void init_hardware() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Initializing SPI Bus on Port A...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Initializing I2C Bus on Port B...&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 4. Finalize the Merge (Student B) ===&lt;br /&gt;
Now that the conflict is manually fixed, tell Git it is resolved:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git commit -m &amp;quot;Resolve merge conflict between SPI and I2C initialization&amp;quot;&lt;br /&gt;
git push origin feature-i2c-init&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 5. Final Approval (Student A) ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Student A:&amp;#039;&amp;#039;&amp;#039; Go to Student B&amp;#039;s Merge Request on GitLab. &lt;br /&gt;
* Notice the conflict warning is gone. The MR is green again!&lt;br /&gt;
* Review the Changes to ensure both SPI and I2C are initialized.&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Approve&amp;#039;&amp;#039;&amp;#039;, then click &amp;#039;&amp;#039;&amp;#039;Merge&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Lab Deliverable ==&lt;br /&gt;
To receive full credit for this week&amp;#039;s lab, both partners must call the professor or teaching assistant over to your workstation and demonstrate:&lt;br /&gt;
# The shared GitLab repository showing the &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; branch with both SPI and I2C logic combined.&lt;br /&gt;
# The &amp;#039;&amp;#039;&amp;#039;Settings -&amp;gt; Repository -&amp;gt; Protected branches&amp;#039;&amp;#039;&amp;#039; screen showing that &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; cannot be pushed to directly.&lt;br /&gt;
# The &amp;#039;&amp;#039;&amp;#039;Merge Requests&amp;#039;&amp;#039;&amp;#039; tab showing two Closed/Merged MRs with review comments visible.&lt;br /&gt;
# Run &amp;lt;code&amp;gt;git log --graph --oneline&amp;lt;/code&amp;gt; on your terminal to show the visual graph of the diverging branches and the merge commit.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=Software_Development_Process_and_Testing&amp;diff=8280</id>
		<title>Software Development Process and Testing</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=Software_Development_Process_and_Testing&amp;diff=8280"/>
		<updated>2026-03-02T13:42:59Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[SDPT Lab 1]]&lt;br /&gt;
* [[SDPT Lab 2]]&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=Main_Page&amp;diff=8279</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=Main_Page&amp;diff=8279"/>
		<updated>2026-03-02T13:42:39Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Laboratories List */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The purpose of this page is the index the lab tutorials and tasks, as well as the auxiliary resources for the lectures and laboratories taught within the DCAE department.&lt;br /&gt;
&lt;br /&gt;
== Course List ==&lt;br /&gt;
&lt;br /&gt;
* [[Integrated Digital Circuits (lecture)]]&lt;br /&gt;
* [[Data Structures and Algorithms]]&lt;br /&gt;
* [[Power Semiconductor Devices]]&lt;br /&gt;
&lt;br /&gt;
== Laboratories List ==&lt;br /&gt;
* [[Advanced Digital Systems]]&lt;br /&gt;
* [[Data Structures and Algorithms (lab)]]&lt;br /&gt;
* [[Digital Integrated Circuits (lab)|Digital Integrated Circuits]]&lt;br /&gt;
* [[Digital Integrated Circuits (old lab)|Digital Integrated Circuits - old]]&lt;br /&gt;
* [[Object Oriented Programming]]&lt;br /&gt;
* [[Power Semiconductor Devices (lab)]]&lt;br /&gt;
* [https://users.dcae.pub.ro/~zhascsi/courses/dsd/dsd.html Digital Systems Design Project]&lt;br /&gt;
* [[Electronic Devices(lab)]]&lt;br /&gt;
* [[Electronic Circuits(lab)]]&lt;br /&gt;
* [[Software Development Process and Testing]]&lt;br /&gt;
&lt;br /&gt;
== Seminaries List ==&lt;br /&gt;
* [[Digital Integrated Circuits (sem)|Digital Integrated Circuits]]&lt;br /&gt;
&lt;br /&gt;
== Applications List ==&lt;br /&gt;
* [[Digital Integrated Circuits (app)|Digital Integrated Circuits]]&lt;br /&gt;
&lt;br /&gt;
== Project List ==&lt;br /&gt;
* [[Project 1 - Electronic Devices and Circuits |Electronic Devices and Circuits (Project 1)]]&lt;br /&gt;
&lt;br /&gt;
* [[Project Master |Project Master]]&lt;br /&gt;
&lt;br /&gt;
== Evaluation Forms ==&lt;br /&gt;
* [[Evaluation Forms 2014-2015, Semester I]]&lt;br /&gt;
* [[Evaluation Forms 2014-2015, Semester II]]&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=Software_Development_Process_and_Testing&amp;diff=8278</id>
		<title>Software Development Process and Testing</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=Software_Development_Process_and_Testing&amp;diff=8278"/>
		<updated>2026-03-02T13:42:03Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: Rhobincu a redenumit pagina Software Development Process and Resting în Software Development Process and Testing fără a lăsa o redirecționare în loc&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[SDPT Lab 1]]&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_1&amp;diff=8270</id>
		<title>SDPT Lab 1</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_1&amp;diff=8270"/>
		<updated>2026-02-23T00:41:41Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Part 1: Secure Authentication (SSH Keys) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Lab 1: Foundation of Process - Git and GitLab Basics =&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Welcome to the first lab of Software Development Process and Testing (SDPT). In our lecture, we discussed why treating software like a physical breadboard leads to failure in complex systems. We introduced the Software Development Life Cycle (SDLC), Issue Tracking, and the underlying graph model of Git.&lt;br /&gt;
&lt;br /&gt;
Today, we put theory into practice. By the end of this 2-hour lab, you will have:&lt;br /&gt;
# Configured secure SSH authentication with your GitLab server.&lt;br /&gt;
# Created a project repository and your first tracked Issue.&lt;br /&gt;
# Configured Git on your local machine.&lt;br /&gt;
# Moved a C++ source file through the Three States of Git.&lt;br /&gt;
# Prevented binary files from entering your repository using &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Pushed your local history to the remote GitLab server to automatically close your Issue.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039; Do not rush. The goal is to understand &amp;#039;&amp;#039;where&amp;#039;&amp;#039; your files are in the Git graph at any given moment. Run &amp;lt;code&amp;gt;git status&amp;lt;/code&amp;gt; frequently!&lt;br /&gt;
&lt;br /&gt;
== Part 1: Secure Authentication (SSH Keys) ==&lt;br /&gt;
Modern code repositories do not allow you to push code using your standard web password. We must set up a secure cryptographic key pair. &lt;br /&gt;
&lt;br /&gt;
=== 1. Generate an SSH Key Pair ===&lt;br /&gt;
Open your terminal (Linux/macOS) or Git Bash (Windows) and type:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh-keygen -t ed25519 -C &amp;quot;your.university.email@stud.####.upb.ro&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Press &amp;#039;&amp;#039;&amp;#039;Enter&amp;#039;&amp;#039;&amp;#039; to accept the default file location.&lt;br /&gt;
* Press &amp;#039;&amp;#039;&amp;#039;Enter&amp;#039;&amp;#039;&amp;#039; twice to skip creating a passphrase (for the sake of this lab environment).&lt;br /&gt;
&lt;br /&gt;
This generated two files: a private key (never share this!) and a public key.&lt;br /&gt;
&lt;br /&gt;
=== 2. Add the Public Key to GitLab ===&lt;br /&gt;
Display your public key in the terminal and copy the output exactly:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cat ~/.ssh/id_ed25519.pub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Log into your university GitLab account in your browser.&lt;br /&gt;
* Click your profile avatar (top right) -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Edit profile&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;SSH Keys&amp;#039;&amp;#039;&amp;#039; (on the left sidebar).&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Add new key&amp;#039;&amp;#039;&amp;#039;. Paste your copied key into the &amp;quot;Key&amp;quot; box. Title it &amp;quot;My Lab Laptop&amp;quot; and click &amp;#039;&amp;#039;&amp;#039;Add key&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
== Part 2: Setting Up the Remote (GitLab) ==&lt;br /&gt;
Before we write code, we document our work.&lt;br /&gt;
&lt;br /&gt;
=== 1. Create a New Repository ===&lt;br /&gt;
* Go to the GitLab homepage. Click &amp;#039;&amp;#039;&amp;#039;New Project&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Create blank project&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Project Name:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;sdpt-rfid-access&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Visibility Level:&amp;#039;&amp;#039;&amp;#039; Private (or Internal).&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Important:&amp;#039;&amp;#039;&amp;#039; Uncheck &amp;quot;Initialize repository with a README&amp;quot;. We want an entirely empty repository.&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Create project&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
=== 2. Create Your First Issue ===&lt;br /&gt;
* On the left sidebar of your new project, navigate to &amp;#039;&amp;#039;&amp;#039;Plan&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Issues&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;New issue&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Title:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;Create initial RFID reader driver skeleton&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Description:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;Need a basic main.cpp file that will eventually hold the SPI communication logic for the RFID module.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Create issue&amp;#039;&amp;#039;&amp;#039;. Take note of the &amp;#039;&amp;#039;&amp;#039;Issue Number&amp;#039;&amp;#039;&amp;#039; (e.g., &amp;lt;code&amp;gt;#1&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Part 3: Initializing the Local Environment ==&lt;br /&gt;
=== 1. Configure Your Identity ===&lt;br /&gt;
Git embeds your name and email into every commit permanently. Run these once:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git config --global user.name &amp;quot;Your First and Last Name&amp;quot;&lt;br /&gt;
git config --global user.email &amp;quot;your.university.email@domain.edu&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. Create Your Local Workspace ===&lt;br /&gt;
Create a folder for your project and initialize it as a Git repository.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mkdir sdpt-rfid-access&lt;br /&gt;
cd sdpt-rfid-access&lt;br /&gt;
git init&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Part 4: Ignoring the Noise (.gitignore) ==&lt;br /&gt;
In C/C++, compiling creates binary files (like &amp;lt;code&amp;gt;.o&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.out&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;.exe&amp;lt;/code&amp;gt;). We &amp;#039;&amp;#039;&amp;#039;never&amp;#039;&amp;#039;&amp;#039; track compiled binaries in Git—we only track human-readable source code!&lt;br /&gt;
&lt;br /&gt;
Let&amp;#039;s tell Git to permanently ignore build files.&lt;br /&gt;
Create a file named exactly &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
touch .gitignore&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Open it in your editor and add these lines:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
# Ignore compiled binaries&lt;br /&gt;
*.o&lt;br /&gt;
*.out&lt;br /&gt;
*.exe&lt;br /&gt;
# Ignore IDE folders&lt;br /&gt;
.vscode/&lt;br /&gt;
.idea/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save the file. Let&amp;#039;s stage and commit our configuration:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add .gitignore&lt;br /&gt;
git commit -m &amp;quot;Add .gitignore for C++ project&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Part 5: The Three States in Practice ==&lt;br /&gt;
Let&amp;#039;s move our actual source code through the Working Directory, Staging Area, and Repository. &lt;br /&gt;
&lt;br /&gt;
=== 1. The Working Directory ===&lt;br /&gt;
Create your C++ file:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
touch main.cpp&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Open &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; and add a basic skeleton:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;RFID Access Control System Initialized&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Check your radar:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git status&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Notice &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; is red. It is Untracked.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 2. The Staging Area (Index) ===&lt;br /&gt;
Tell Git to include this in the next snapshot.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git status&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;It is now green. It is Staged.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 3. Time Travel and Diffs ===&lt;br /&gt;
Wait! Before committing, what exactly did we just stage? It&amp;#039;s good practice to review your code.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git diff --staged&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This shows you the exact lines of C++ you are about to commit. Press &amp;lt;code&amp;gt;q&amp;lt;/code&amp;gt; to exit the diff view if it pauses.&lt;br /&gt;
&lt;br /&gt;
=== 4. The Repository (Commit) ===&lt;br /&gt;
Save the snapshot permanently.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git commit -m &amp;quot;Add initial RFID system skeleton&amp;quot;&lt;br /&gt;
git status&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Part 6: Connecting Local to Remote and Closing Issues ==&lt;br /&gt;
Your code is safe locally, but the &amp;quot;Bus Factor&amp;quot; is still 1. We must push to GitLab using the SSH key we created earlier.&lt;br /&gt;
&lt;br /&gt;
=== 1. Link the Remote Server ===&lt;br /&gt;
Go back to your GitLab project page. Under &amp;quot;Push an existing Git repository&amp;quot;, click the &amp;#039;&amp;#039;&amp;#039;SSH&amp;#039;&amp;#039;&amp;#039; button (not HTTPS) and copy the &amp;lt;code&amp;gt;git remote add origin...&amp;lt;/code&amp;gt; command. It will look like this:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git remote add origin git@gitlab.com:your-username/sdpt-rfid-access.git&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Paste and run that in your terminal.&lt;br /&gt;
&lt;br /&gt;
=== 2. Push and Close the Issue ===&lt;br /&gt;
Let&amp;#039;s make one final change to fulfill our Issue requirement and close it automatically.&lt;br /&gt;
Open &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; and add a comment:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
// TODO: Implement SPI communication with RC522 module&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stage and commit this change, using the special keyword (&amp;lt;code&amp;gt;Closes #1&amp;lt;/code&amp;gt;) in your commit message:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git commit -m &amp;quot;Add SPI TODO comment. Closes #1&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Push your local graph to the remote server:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push -u origin main&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;(Note: If Git complains about &amp;#039;main&amp;#039;, try &amp;lt;code&amp;gt;git push -u origin master&amp;lt;/code&amp;gt;, or ask your professor how to rename your default branch).&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
When prompted &amp;quot;Are you sure you want to continue connecting?&amp;quot;, type &amp;lt;code&amp;gt;yes&amp;lt;/code&amp;gt; and press Enter.&lt;br /&gt;
&lt;br /&gt;
=== 3. Verify the Magic ===&lt;br /&gt;
Refresh your GitLab project page in your browser:&lt;br /&gt;
* Your &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt; files are visible!&lt;br /&gt;
* Go to &amp;#039;&amp;#039;&amp;#039;Plan&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Issues&amp;#039;&amp;#039;&amp;#039;. Notice that Issue #1 is now automatically marked as &amp;#039;&amp;#039;&amp;#039;Closed&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
== Lab Deliverable ==&lt;br /&gt;
To receive full credit for this week&amp;#039;s lab, call the professor or teaching assistant over to your workstation and demonstrate:&lt;br /&gt;
# Your GitLab repository showing the code and the &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt; file.&lt;br /&gt;
# Your GitLab Issue board showing Issue #1 as Closed.&lt;br /&gt;
# Your terminal showing the output of the &amp;lt;code&amp;gt;git log --oneline&amp;lt;/code&amp;gt; command, displaying your three commits.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_1&amp;diff=8269</id>
		<title>SDPT Lab 1</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_1&amp;diff=8269"/>
		<updated>2026-02-23T00:40:39Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Lab 1: Foundation of Process - Git and GitLab Basics =&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Welcome to the first lab of Software Development Process and Testing (SDPT). In our lecture, we discussed why treating software like a physical breadboard leads to failure in complex systems. We introduced the Software Development Life Cycle (SDLC), Issue Tracking, and the underlying graph model of Git.&lt;br /&gt;
&lt;br /&gt;
Today, we put theory into practice. By the end of this 2-hour lab, you will have:&lt;br /&gt;
# Configured secure SSH authentication with your GitLab server.&lt;br /&gt;
# Created a project repository and your first tracked Issue.&lt;br /&gt;
# Configured Git on your local machine.&lt;br /&gt;
# Moved a C++ source file through the Three States of Git.&lt;br /&gt;
# Prevented binary files from entering your repository using &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Pushed your local history to the remote GitLab server to automatically close your Issue.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039; Do not rush. The goal is to understand &amp;#039;&amp;#039;where&amp;#039;&amp;#039; your files are in the Git graph at any given moment. Run &amp;lt;code&amp;gt;git status&amp;lt;/code&amp;gt; frequently!&lt;br /&gt;
&lt;br /&gt;
== Part 1: Secure Authentication (SSH Keys) ==&lt;br /&gt;
Modern code repositories do not allow you to push code using your standard web password. We must set up a secure cryptographic key pair. &lt;br /&gt;
&lt;br /&gt;
=== 1. Generate an SSH Key Pair ===&lt;br /&gt;
Open your terminal (Linux/macOS) or Git Bash (Windows) and type:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh-keygen -t ed25519 -C &amp;quot;your.university.email@domain.edu&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Press &amp;#039;&amp;#039;&amp;#039;Enter&amp;#039;&amp;#039;&amp;#039; to accept the default file location.&lt;br /&gt;
* Press &amp;#039;&amp;#039;&amp;#039;Enter&amp;#039;&amp;#039;&amp;#039; twice to skip creating a passphrase (for the sake of this lab environment).&lt;br /&gt;
&lt;br /&gt;
This generated two files: a private key (never share this!) and a public key.&lt;br /&gt;
&lt;br /&gt;
=== 2. Add the Public Key to GitLab ===&lt;br /&gt;
Display your public key in the terminal and copy the output exactly:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cat ~/.ssh/id_ed25519.pub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Log into your university GitLab account in your browser.&lt;br /&gt;
* Click your profile avatar (top right) -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Edit profile&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;SSH Keys&amp;#039;&amp;#039;&amp;#039; (on the left sidebar).&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Add new key&amp;#039;&amp;#039;&amp;#039;. Paste your copied key into the &amp;quot;Key&amp;quot; box. Title it &amp;quot;My Lab Laptop&amp;quot; and click &amp;#039;&amp;#039;&amp;#039;Add key&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
== Part 2: Setting Up the Remote (GitLab) ==&lt;br /&gt;
Before we write code, we document our work.&lt;br /&gt;
&lt;br /&gt;
=== 1. Create a New Repository ===&lt;br /&gt;
* Go to the GitLab homepage. Click &amp;#039;&amp;#039;&amp;#039;New Project&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Create blank project&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Project Name:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;sdpt-rfid-access&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Visibility Level:&amp;#039;&amp;#039;&amp;#039; Private (or Internal).&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Important:&amp;#039;&amp;#039;&amp;#039; Uncheck &amp;quot;Initialize repository with a README&amp;quot;. We want an entirely empty repository.&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Create project&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
=== 2. Create Your First Issue ===&lt;br /&gt;
* On the left sidebar of your new project, navigate to &amp;#039;&amp;#039;&amp;#039;Plan&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Issues&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;New issue&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Title:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;Create initial RFID reader driver skeleton&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Description:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;Need a basic main.cpp file that will eventually hold the SPI communication logic for the RFID module.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Create issue&amp;#039;&amp;#039;&amp;#039;. Take note of the &amp;#039;&amp;#039;&amp;#039;Issue Number&amp;#039;&amp;#039;&amp;#039; (e.g., &amp;lt;code&amp;gt;#1&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Part 3: Initializing the Local Environment ==&lt;br /&gt;
=== 1. Configure Your Identity ===&lt;br /&gt;
Git embeds your name and email into every commit permanently. Run these once:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git config --global user.name &amp;quot;Your First and Last Name&amp;quot;&lt;br /&gt;
git config --global user.email &amp;quot;your.university.email@domain.edu&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. Create Your Local Workspace ===&lt;br /&gt;
Create a folder for your project and initialize it as a Git repository.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mkdir sdpt-rfid-access&lt;br /&gt;
cd sdpt-rfid-access&lt;br /&gt;
git init&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Part 4: Ignoring the Noise (.gitignore) ==&lt;br /&gt;
In C/C++, compiling creates binary files (like &amp;lt;code&amp;gt;.o&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.out&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;.exe&amp;lt;/code&amp;gt;). We &amp;#039;&amp;#039;&amp;#039;never&amp;#039;&amp;#039;&amp;#039; track compiled binaries in Git—we only track human-readable source code!&lt;br /&gt;
&lt;br /&gt;
Let&amp;#039;s tell Git to permanently ignore build files.&lt;br /&gt;
Create a file named exactly &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
touch .gitignore&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Open it in your editor and add these lines:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
# Ignore compiled binaries&lt;br /&gt;
*.o&lt;br /&gt;
*.out&lt;br /&gt;
*.exe&lt;br /&gt;
# Ignore IDE folders&lt;br /&gt;
.vscode/&lt;br /&gt;
.idea/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save the file. Let&amp;#039;s stage and commit our configuration:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add .gitignore&lt;br /&gt;
git commit -m &amp;quot;Add .gitignore for C++ project&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Part 5: The Three States in Practice ==&lt;br /&gt;
Let&amp;#039;s move our actual source code through the Working Directory, Staging Area, and Repository. &lt;br /&gt;
&lt;br /&gt;
=== 1. The Working Directory ===&lt;br /&gt;
Create your C++ file:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
touch main.cpp&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Open &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; and add a basic skeleton:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;RFID Access Control System Initialized&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Check your radar:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git status&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Notice &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; is red. It is Untracked.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 2. The Staging Area (Index) ===&lt;br /&gt;
Tell Git to include this in the next snapshot.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git status&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;It is now green. It is Staged.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 3. Time Travel and Diffs ===&lt;br /&gt;
Wait! Before committing, what exactly did we just stage? It&amp;#039;s good practice to review your code.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git diff --staged&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This shows you the exact lines of C++ you are about to commit. Press &amp;lt;code&amp;gt;q&amp;lt;/code&amp;gt; to exit the diff view if it pauses.&lt;br /&gt;
&lt;br /&gt;
=== 4. The Repository (Commit) ===&lt;br /&gt;
Save the snapshot permanently.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git commit -m &amp;quot;Add initial RFID system skeleton&amp;quot;&lt;br /&gt;
git status&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Part 6: Connecting Local to Remote and Closing Issues ==&lt;br /&gt;
Your code is safe locally, but the &amp;quot;Bus Factor&amp;quot; is still 1. We must push to GitLab using the SSH key we created earlier.&lt;br /&gt;
&lt;br /&gt;
=== 1. Link the Remote Server ===&lt;br /&gt;
Go back to your GitLab project page. Under &amp;quot;Push an existing Git repository&amp;quot;, click the &amp;#039;&amp;#039;&amp;#039;SSH&amp;#039;&amp;#039;&amp;#039; button (not HTTPS) and copy the &amp;lt;code&amp;gt;git remote add origin...&amp;lt;/code&amp;gt; command. It will look like this:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git remote add origin git@gitlab.com:your-username/sdpt-rfid-access.git&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Paste and run that in your terminal.&lt;br /&gt;
&lt;br /&gt;
=== 2. Push and Close the Issue ===&lt;br /&gt;
Let&amp;#039;s make one final change to fulfill our Issue requirement and close it automatically.&lt;br /&gt;
Open &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; and add a comment:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
// TODO: Implement SPI communication with RC522 module&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stage and commit this change, using the special keyword (&amp;lt;code&amp;gt;Closes #1&amp;lt;/code&amp;gt;) in your commit message:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git commit -m &amp;quot;Add SPI TODO comment. Closes #1&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Push your local graph to the remote server:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push -u origin main&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;(Note: If Git complains about &amp;#039;main&amp;#039;, try &amp;lt;code&amp;gt;git push -u origin master&amp;lt;/code&amp;gt;, or ask your professor how to rename your default branch).&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
When prompted &amp;quot;Are you sure you want to continue connecting?&amp;quot;, type &amp;lt;code&amp;gt;yes&amp;lt;/code&amp;gt; and press Enter.&lt;br /&gt;
&lt;br /&gt;
=== 3. Verify the Magic ===&lt;br /&gt;
Refresh your GitLab project page in your browser:&lt;br /&gt;
* Your &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt; files are visible!&lt;br /&gt;
* Go to &amp;#039;&amp;#039;&amp;#039;Plan&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Issues&amp;#039;&amp;#039;&amp;#039;. Notice that Issue #1 is now automatically marked as &amp;#039;&amp;#039;&amp;#039;Closed&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
== Lab Deliverable ==&lt;br /&gt;
To receive full credit for this week&amp;#039;s lab, call the professor or teaching assistant over to your workstation and demonstrate:&lt;br /&gt;
# Your GitLab repository showing the code and the &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt; file.&lt;br /&gt;
# Your GitLab Issue board showing Issue #1 as Closed.&lt;br /&gt;
# Your terminal showing the output of the &amp;lt;code&amp;gt;git log --oneline&amp;lt;/code&amp;gt; command, displaying your three commits.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_1&amp;diff=8268</id>
		<title>SDPT Lab 1</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_1&amp;diff=8268"/>
		<updated>2026-02-23T00:39:55Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Lab 1: Foundation of Process - Git and GitLab Basics =&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Welcome to the first lab of Software Development Process and Testing (SDPT). In our lecture, we discussed why treating software like a physical breadboard leads to failure in complex systems. We introduced the Software Development Life Cycle (SDLC), Issue Tracking, and the underlying graph model of Git.&lt;br /&gt;
&lt;br /&gt;
Today, we put theory into practice. By the end of this 2-hour lab, you will have:&lt;br /&gt;
# Configured secure SSH authentication with your GitLab server.&lt;br /&gt;
# Created a project repository and your first tracked Issue.&lt;br /&gt;
# Configured Git on your local machine.&lt;br /&gt;
# Moved a C++ source file through the Three States of Git.&lt;br /&gt;
# Prevented binary files from entering your repository using &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Pushed your local history to the remote GitLab server to automatically close your Issue.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039; Do not rush. The goal is to understand &amp;#039;&amp;#039;where&amp;#039;&amp;#039; your files are in the Git graph at any given moment. Run &amp;lt;code&amp;gt;git status&amp;lt;/code&amp;gt; frequently!&lt;br /&gt;
&lt;br /&gt;
== Part 1: Secure Authentication (SSH Keys) ==&lt;br /&gt;
Modern code repositories do not allow you to push code using your standard web password. We must set up a secure cryptographic key pair. &lt;br /&gt;
&lt;br /&gt;
=== 1. Generate an SSH Key Pair ===&lt;br /&gt;
Open your terminal (Linux/macOS) or Git Bash (Windows) and type:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ssh-keygen -t ed25519 -C &amp;quot;your.university.email@domain.edu&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Press &amp;#039;&amp;#039;&amp;#039;Enter&amp;#039;&amp;#039;&amp;#039; to accept the default file location.&lt;br /&gt;
* Press &amp;#039;&amp;#039;&amp;#039;Enter&amp;#039;&amp;#039;&amp;#039; twice to skip creating a passphrase (for the sake of this lab environment).&lt;br /&gt;
&lt;br /&gt;
This generated two files: a private key (never share this!) and a public key.&lt;br /&gt;
&lt;br /&gt;
=== 2. Add the Public Key to GitLab ===&lt;br /&gt;
Display your public key in the terminal and copy the output exactly:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cat ~/.ssh/id_ed25519.pub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Log into your university GitLab account in your browser.&lt;br /&gt;
* Click your profile avatar (top right) -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Edit profile&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;SSH Keys&amp;#039;&amp;#039;&amp;#039; (on the left sidebar).&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Add new key&amp;#039;&amp;#039;&amp;#039;. Paste your copied key into the &amp;quot;Key&amp;quot; box. Title it &amp;quot;My Lab Laptop&amp;quot; and click &amp;#039;&amp;#039;&amp;#039;Add key&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
== Part 2: Setting Up the Remote (GitLab) ==&lt;br /&gt;
Before we write code, we document our work.&lt;br /&gt;
&lt;br /&gt;
=== 1. Create a New Repository ===&lt;br /&gt;
* Go to the GitLab homepage. Click &amp;#039;&amp;#039;&amp;#039;New Project&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Create blank project&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Project Name:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;sdpt-rfid-access&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Visibility Level:&amp;#039;&amp;#039;&amp;#039; Private (or Internal).&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Important:&amp;#039;&amp;#039;&amp;#039; Uncheck &amp;quot;Initialize repository with a README&amp;quot;. We want an entirely empty repository.&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Create project&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
=== 2. Create Your First Issue ===&lt;br /&gt;
* On the left sidebar of your new project, navigate to &amp;#039;&amp;#039;&amp;#039;Plan&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Issues&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;New issue&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Title:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;Create initial RFID reader driver skeleton&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Description:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;Need a basic main.cpp file that will eventually hold the SPI communication logic for the RFID module.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Create issue&amp;#039;&amp;#039;&amp;#039;. Take note of the &amp;#039;&amp;#039;&amp;#039;Issue Number&amp;#039;&amp;#039;&amp;#039; (e.g., &amp;lt;code&amp;gt;#1&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Part 3: Initializing the Local Environment ==&lt;br /&gt;
=== 1. Configure Your Identity ===&lt;br /&gt;
Git embeds your name and email into every commit permanently. Run these once:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git config --global user.name &amp;quot;Your First and Last Name&amp;quot;&lt;br /&gt;
git config --global user.email &amp;quot;your.university.email@domain.edu&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. Create Your Local Workspace ===&lt;br /&gt;
Create a folder for your project and initialize it as a Git repository.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mkdir sdpt-rfid-access&lt;br /&gt;
cd sdpt-rfid-access&lt;br /&gt;
git init&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Part 4: Ignoring the Noise (.gitignore) ==&lt;br /&gt;
In C/C++, compiling creates binary files (like &amp;lt;code&amp;gt;.o&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.out&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;.exe&amp;lt;/code&amp;gt;). We &amp;#039;&amp;#039;&amp;#039;never&amp;#039;&amp;#039;&amp;#039; track compiled binaries in Git—we only track human-readable source code!&lt;br /&gt;
&lt;br /&gt;
Let&amp;#039;s tell Git to permanently ignore build files.&lt;br /&gt;
Create a file named exactly &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
touch .gitignore&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Open it in your editor and add these lines:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
# Ignore compiled binaries&lt;br /&gt;
*.o&lt;br /&gt;
*.out&lt;br /&gt;
*.exe&lt;br /&gt;
# Ignore IDE folders&lt;br /&gt;
.vscode/&lt;br /&gt;
.idea/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save the file. Let&amp;#039;s stage and commit our configuration:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add .gitignore&lt;br /&gt;
git commit -m &amp;quot;Add .gitignore for C++ project&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Part 5: The Three States in Practice ==&lt;br /&gt;
Let&amp;#039;s move our actual source code through the Working Directory, Staging Area, and Repository. &lt;br /&gt;
&lt;br /&gt;
=== 1. The Working Directory ===&lt;br /&gt;
Create your C++ file:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
touch main.cpp&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Open &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; and add a basic skeleton:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;RFID Access Control System Initialized&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Check your radar:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git status&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Notice &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; is red. It is Untracked.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 2. The Staging Area (Index) ===&lt;br /&gt;
Tell Git to include this in the next snapshot.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git status&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;It is now green. It is Staged.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 3. Time Travel and Diffs ===&lt;br /&gt;
Wait! Before committing, what exactly did we just stage? It&amp;#039;s good practice to review your code.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git diff --staged&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This shows you the exact lines of C++ you are about to commit. Press &amp;lt;code&amp;gt;q&amp;lt;/code&amp;gt; to exit the diff view if it pauses.&lt;br /&gt;
&lt;br /&gt;
=== 4. The Repository (Commit) ===&lt;br /&gt;
Save the snapshot permanently.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git commit -m &amp;quot;Add initial RFID system skeleton&amp;quot;&lt;br /&gt;
git status&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 6: Connecting Local to Remote and Closing Issues ==&lt;br /&gt;
Your code is safe locally, but the &amp;quot;Bus Factor&amp;quot; is still 1. We must push to GitLab using the SSH key we created earlier.&lt;br /&gt;
&lt;br /&gt;
=== 1. Link the Remote Server ===&lt;br /&gt;
Go back to your GitLab project page. Under &amp;quot;Push an existing Git repository&amp;quot;, click the &amp;#039;&amp;#039;&amp;#039;SSH&amp;#039;&amp;#039;&amp;#039; button (not HTTPS) and copy the &amp;lt;code&amp;gt;git remote add origin...&amp;lt;/code&amp;gt; command. It will look like this:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git remote add origin git@gitlab.com:your-username/sdpt-rfid-access.git&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Paste and run that in your terminal.&lt;br /&gt;
&lt;br /&gt;
=== 2. Push and Close the Issue ===&lt;br /&gt;
Let&amp;#039;s make one final change to fulfill our Issue requirement and close it automatically.&lt;br /&gt;
Open &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; and add a comment:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
// TODO: Implement SPI communication with RC522 module&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stage and commit this change, using the special keyword (&amp;lt;code&amp;gt;Closes #1&amp;lt;/code&amp;gt;) in your commit message:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git commit -m &amp;quot;Add SPI TODO comment. Closes #1&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Push your local graph to the remote server:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push -u origin main&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;(Note: If Git complains about &amp;#039;main&amp;#039;, try &amp;lt;code&amp;gt;git push -u origin master&amp;lt;/code&amp;gt;, or ask your professor how to rename your default branch).&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
When prompted &amp;quot;Are you sure you want to continue connecting?&amp;quot;, type &amp;lt;code&amp;gt;yes&amp;lt;/code&amp;gt; and press Enter.&lt;br /&gt;
&lt;br /&gt;
=== 3. Verify the Magic ===&lt;br /&gt;
Refresh your GitLab project page in your browser:&lt;br /&gt;
* Your &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt; files are visible!&lt;br /&gt;
* Go to &amp;#039;&amp;#039;&amp;#039;Plan&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Issues&amp;#039;&amp;#039;&amp;#039;. Notice that Issue #1 is now automatically marked as &amp;#039;&amp;#039;&amp;#039;Closed&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Lab Deliverable ==&lt;br /&gt;
To receive full credit for this week&amp;#039;s lab, call the professor or teaching assistant over to your workstation and demonstrate:&lt;br /&gt;
# Your GitLab repository showing the code and the &amp;lt;code&amp;gt;.gitignore&amp;lt;/code&amp;gt; file.&lt;br /&gt;
# Your GitLab Issue board showing Issue #1 as Closed.&lt;br /&gt;
# Your terminal showing the output of the &amp;lt;code&amp;gt;git log --oneline&amp;lt;/code&amp;gt; command, displaying your three commits.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_1&amp;diff=8267</id>
		<title>SDPT Lab 1</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDPT_Lab_1&amp;diff=8267"/>
		<updated>2026-02-23T00:34:29Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: Pagină nouă: = Lab 1: Foundation of Process - Git and GitLab Basics =  == Introduction == Welcome to the first lab of Software Development Process and Testing (SDPT). In our lecture, we discuss...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Lab 1: Foundation of Process - Git and GitLab Basics =&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Welcome to the first lab of Software Development Process and Testing (SDPT). In our lecture, we discussed why treating software like a physical breadboard leads to failure in complex systems. We introduced the Software Development Life Cycle (SDLC), Issue Tracking, and the underlying graph model of Git.&lt;br /&gt;
&lt;br /&gt;
Today, we put theory into practice. By the end of this 2-hour lab, you will have:&lt;br /&gt;
# Created a project repository on GitLab.&lt;br /&gt;
# Created your first tracked Issue.&lt;br /&gt;
# Configured Git on your local machine.&lt;br /&gt;
# Moved a C++ source file through the Three States of Git.&lt;br /&gt;
# Pushed your local history to the remote GitLab server and automatically closed your Issue.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039; Do not rush. The goal is to understand &amp;#039;&amp;#039;where&amp;#039;&amp;#039; your files are in the Git graph at any given moment. Run &amp;lt;code&amp;gt;git status&amp;lt;/code&amp;gt; frequently!&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 1: Setting Up the Remote (GitLab) ==&lt;br /&gt;
Before we touch the terminal, we need to set up our remote infrastructure and document the work we intend to do.&lt;br /&gt;
&lt;br /&gt;
=== 1. Create a New Repository ===&lt;br /&gt;
* Log into your university GitLab account.&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;New Project&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Create blank project&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Project Name:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;sdpt-rfid-access&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Visibility Level:&amp;#039;&amp;#039;&amp;#039; Private (or Internal, depending on your professor&amp;#039;s instructions).&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Important:&amp;#039;&amp;#039;&amp;#039; Uncheck &amp;quot;Initialize repository with a README&amp;quot;. We want an entirely empty repository to practice pushing from our local machine.&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Create project&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
=== 2. Create Your First Issue ===&lt;br /&gt;
We need a business requirement before we write code. &lt;br /&gt;
* On the left sidebar of your new project, navigate to &amp;#039;&amp;#039;&amp;#039;Plan&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Issues&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;New issue&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Title:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;Create initial RFID reader driver skeleton&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Description:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;Need a basic main.cpp file that will eventually hold the SPI communication logic for the RFID module.&amp;lt;/code&amp;gt;&lt;br /&gt;
* Click &amp;#039;&amp;#039;&amp;#039;Create issue&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* Take note of the &amp;#039;&amp;#039;&amp;#039;Issue Number&amp;#039;&amp;#039;&amp;#039; (e.g., &amp;lt;code&amp;gt;#1&amp;lt;/code&amp;gt;) generated next to the title. You will need this later!&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 2: Initializing the Local Environment ==&lt;br /&gt;
Now, open your terminal (Linux/macOS) or Git Bash (Windows). &lt;br /&gt;
&lt;br /&gt;
=== 1. Configure Your Identity ===&lt;br /&gt;
Git embeds the author&amp;#039;s name and email into every commit permanently. You only need to run these commands once per computer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git config --global user.name &amp;quot;Your First and Last Name&amp;quot;&lt;br /&gt;
git config --global user.email &amp;quot;your.university.email@domain.edu&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. Create Your Local Workspace ===&lt;br /&gt;
Create a folder for your project and initialize it as a Git repository.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mkdir sdpt-rfid-access&lt;br /&gt;
cd sdpt-rfid-access&lt;br /&gt;
git init&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice the output: &amp;lt;code&amp;gt;Initialized empty Git repository&amp;lt;/code&amp;gt;. A hidden &amp;lt;code&amp;gt;.git&amp;lt;/code&amp;gt; folder has been created. This is your database.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 3: The Three States in Practice ==&lt;br /&gt;
Remember the three states from the lecture: Working Directory, Staging Area, and Repository. Let&amp;#039;s move a file through them. &lt;br /&gt;
&lt;br /&gt;
=== 1. The Working Directory ===&lt;br /&gt;
Create a new C++ file. This represents writing your initial code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
touch main.cpp&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Open &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; in your favorite text editor (nano, vim, VS Code) and add a basic skeleton:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;RFID Access Control System Initialized&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, check your radar:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git status&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Notice that &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; is red and listed under &amp;quot;Untracked files&amp;quot;. Git sees the file in your Working Directory, but is not managing it yet.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 2. The Staging Area (Index) ===&lt;br /&gt;
Tell Git you want to include this file in your next commit snapshot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git status&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Notice the file is now green and under &amp;quot;Changes to be committed&amp;quot;. It is in the Staging Area.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 3. The Repository (Commit) ===&lt;br /&gt;
Save the snapshot permanently into your local Git database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git commit -m &amp;quot;Add initial RFID system skeleton&amp;quot;&lt;br /&gt;
git status&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Your working tree is now clean. The snapshot is stored as a node in your local Git graph.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Part 4: Connecting Local to Remote and Closing Issues ==&lt;br /&gt;
Your code is safe locally, but the &amp;quot;Bus Factor&amp;quot; is still 1. If your laptop crashes, the code is gone. We must push to GitLab.&lt;br /&gt;
&lt;br /&gt;
=== 1. Link the Remote Server ===&lt;br /&gt;
Go back to your GitLab project page. Under &amp;quot;Push an existing Git repository&amp;quot;, copy the &amp;lt;code&amp;gt;git remote add origin...&amp;lt;/code&amp;gt; command. It will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git remote add origin https://gitlab.com/your-username/sdpt-rfid-access.git&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. Push and Close the Issue ===&lt;br /&gt;
We want to push our code AND tell GitLab that this code fulfills the requirement we documented in Part 1. We do this by making a new commit that references the Issue number.&lt;br /&gt;
&lt;br /&gt;
Let&amp;#039;s make a small change to &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt;. Open it and add a comment:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
// TODO: Implement SPI communication with RC522 module&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, stage and commit this change, using a special keyword (&amp;lt;code&amp;gt;Closes #1&amp;lt;/code&amp;gt;) in the commit message:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git add main.cpp&lt;br /&gt;
git commit -m &amp;quot;Add SPI TODO comment. Closes #1&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, push your local graph to the remote server:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git push -u origin main&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;(Note: If your default branch is &amp;#039;master&amp;#039; instead of &amp;#039;main&amp;#039;, use &amp;lt;code&amp;gt;git push -u origin master&amp;lt;/code&amp;gt;)&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== 3. Verify the Magic ===&lt;br /&gt;
Go back to your browser and refresh your GitLab project page:&lt;br /&gt;
* Your &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; file is now visible on the server!&lt;br /&gt;
* Go to &amp;#039;&amp;#039;&amp;#039;Plan&amp;#039;&amp;#039;&amp;#039; -&amp;gt; &amp;#039;&amp;#039;&amp;#039;Issues&amp;#039;&amp;#039;&amp;#039;. Notice that Issue #1 is now automatically marked as &amp;#039;&amp;#039;&amp;#039;Closed&amp;#039;&amp;#039;&amp;#039;. Git and GitLab worked together to link your code directly to the business requirement.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Lab Deliverable ==&lt;br /&gt;
To receive full credit for this week&amp;#039;s lab, call the professor or teaching assistant over to your workstation and demonstrate:&lt;br /&gt;
# Your GitLab repository showing the &amp;lt;code&amp;gt;main.cpp&amp;lt;/code&amp;gt; file.&lt;br /&gt;
# Your GitLab Issue board showing Issue #1 as Closed.&lt;br /&gt;
# Your terminal showing the output of the &amp;lt;code&amp;gt;git log&amp;lt;/code&amp;gt; command, displaying your two commits.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=Software_Development_Process_and_Testing&amp;diff=8266</id>
		<title>Software Development Process and Testing</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=Software_Development_Process_and_Testing&amp;diff=8266"/>
		<updated>2026-02-23T00:34:18Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: Pagină nouă: * SDPT Lab 1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[SDPT Lab 1]]&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=Main_Page&amp;diff=8265</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=Main_Page&amp;diff=8265"/>
		<updated>2026-02-23T00:33:36Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The purpose of this page is the index the lab tutorials and tasks, as well as the auxiliary resources for the lectures and laboratories taught within the DCAE department.&lt;br /&gt;
&lt;br /&gt;
== Course List ==&lt;br /&gt;
&lt;br /&gt;
* [[Integrated Digital Circuits (lecture)]]&lt;br /&gt;
* [[Data Structures and Algorithms]]&lt;br /&gt;
* [[Power Semiconductor Devices]]&lt;br /&gt;
&lt;br /&gt;
== Laboratories List ==&lt;br /&gt;
* [[Advanced Digital Systems]]&lt;br /&gt;
* [[Data Structures and Algorithms (lab)]]&lt;br /&gt;
* [[Digital Integrated Circuits (lab)|Digital Integrated Circuits]]&lt;br /&gt;
* [[Digital Integrated Circuits (old lab)|Digital Integrated Circuits - old]]&lt;br /&gt;
* [[Object Oriented Programming]]&lt;br /&gt;
* [[Power Semiconductor Devices (lab)]]&lt;br /&gt;
* [https://users.dcae.pub.ro/~zhascsi/courses/dsd/dsd.html Digital Systems Design Project]&lt;br /&gt;
* [[Electronic Devices(lab)]]&lt;br /&gt;
* [[Electronic Circuits(lab)]]&lt;br /&gt;
* [[Software Development Process and Resting]]&lt;br /&gt;
&lt;br /&gt;
== Seminaries List ==&lt;br /&gt;
* [[Digital Integrated Circuits (sem)|Digital Integrated Circuits]]&lt;br /&gt;
&lt;br /&gt;
== Applications List ==&lt;br /&gt;
* [[Digital Integrated Circuits (app)|Digital Integrated Circuits]]&lt;br /&gt;
&lt;br /&gt;
== Project List ==&lt;br /&gt;
* [[Project 1 - Electronic Devices and Circuits |Electronic Devices and Circuits (Project 1)]]&lt;br /&gt;
&lt;br /&gt;
* [[Project Master |Project Master]]&lt;br /&gt;
&lt;br /&gt;
== Evaluation Forms ==&lt;br /&gt;
* [[Evaluation Forms 2014-2015, Semester I]]&lt;br /&gt;
* [[Evaluation Forms 2014-2015, Semester II]]&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=SDA_Lucrarea_1&amp;diff=7751</id>
		<title>SDA Lucrarea 1</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=SDA_Lucrarea_1&amp;diff=7751"/>
		<updated>2024-09-29T18:47:58Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;După acest laborator veți putea folosi IDE-ul Netbeans pentru a scrie și depana programe în C. Totodată veți relua și recapitula noțiunile legate de pointeri în C.&lt;br /&gt;
&lt;br /&gt;
= Utilizarea IDE-ului CLion =&lt;br /&gt;
&lt;br /&gt;
[https://www.jetbrains.com/clion CLion] este un mediu integrat de dezvoltare (IDE) care permite dezvoltarea de programe în limbajele C și C++. CLion nu instalează și compilator pentru C/C++, acesta trebuie instalat manual, în prealabil. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: red; font-weight: bold&amp;quot;&amp;gt;Atenție:&amp;lt;/span&amp;gt; Imaginea de Linux folosită la Programarea Calculatoarelor are deja instalat compilatorul de C.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Instalarea GCC ==&lt;br /&gt;
&lt;br /&gt;
=== Instalarea GCC în Linux ===&lt;br /&gt;
&lt;br /&gt;
Pentru instalarea compilatorului de C (GCC) în distribuțiile de Linux provenite din Ubuntu (Ubuntu, Kubuntu, Xubuntu, Mint, LMDE, etc.) se poate folosi comanda:&lt;br /&gt;
&lt;br /&gt;
 apt-get install -y build-essential&lt;br /&gt;
&lt;br /&gt;
=== Instalarea GCC în Windows ===&lt;br /&gt;
&lt;br /&gt;
Pentru compilarea de programe cu GCC în Windows, aveți nevoie de instalarea acestui compilator care poate fi făcută prin instalarea unuia din următoarele două suite de programe:&lt;br /&gt;
* [https://cygwin.com Cygwin] - Tutorial de instalare [https://cygwin.com/install.html aici].&lt;br /&gt;
* [http://www.mingw.org/ MinGW] - Tutorial de instalare [http://www.mingw.org/wiki/InstallationHOWTOforMinGW aici].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: red; font-weight: bold&amp;quot;&amp;gt;Atenție:&amp;lt;/span&amp;gt; Nu uitați ca la instalare să bifați în lista de pachete și compilatorul de C (&amp;lt;code&amp;gt;gcc&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;git&amp;lt;/code&amp;gt;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Instalarea CLion ==&lt;br /&gt;
&lt;br /&gt;
De la adresa https://www.jetbrains.com/clion/download/#section=linux puteți descărca kitul de instalare pentru sistemul vostru de operare.&lt;br /&gt;
După instalare, urmaţi următorii paşi de configurare, în funcţie de suita de programe aleasă:&lt;br /&gt;
* [https://www.jetbrains.com/help/clion/quick-tutorial-on-configuring-clion-on-windows.html#Cygwin Configurare CLion cu Cygwin]&lt;br /&gt;
* [https://www.jetbrains.com/help/clion/quick-tutorial-on-configuring-clion-on-windows.html#MinGW  Configurare CLion cu MinGW]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Realizarea unui proiect ==&lt;br /&gt;
&lt;br /&gt;
Odată pornit, CLion oferă posibilitatea de a deschide un proiect existent, sau de a crea unul nou. Vrem să realizăm un proiect nou, aşadar se va alege &amp;#039;&amp;#039;&amp;#039;New Project&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt; &amp;#039;&amp;#039;&amp;#039; Observație: &amp;#039;&amp;#039;&amp;#039; Se poate realiza un nou proiect atunci când altul este deja deschis folosind meniul &amp;lt;code&amp;gt;File - New Project &amp;lt;/code&amp;gt; .&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fișier:Welcome_to_clion.png | 600px | Imaginea 1]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt; Mai departe se va selecta categoria &amp;#039;&amp;#039;&amp;#039;C++ Executable&amp;#039;&amp;#039;&amp;#039; şi se va introduce locaţia proiectului.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: red; font-weight: bold&amp;quot;&amp;gt;Atenție:&amp;lt;/span&amp;gt; În imagine se observă că locaţia introdusă este &amp;#039;&amp;#039;&amp;#039;/home/student/projects/NewProject&amp;#039;&amp;#039;&amp;#039;. Se recomandă ca directorul în care se realizează proiectul să aibă numele proiectului, sau un nume sugestiv (în imagine &amp;#039;&amp;#039;&amp;#039;NewProject&amp;#039;&amp;#039;&amp;#039;)&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fișier:New_project_location_clion.png | 600px | Imaginea 2]]&lt;br /&gt;
&lt;br /&gt;
== Componentele IDE-ului CLion == &lt;br /&gt;
&lt;br /&gt;
[[Fișier:CLion_env.png | 1000px | Imaginea 3]]&lt;br /&gt;
&lt;br /&gt;
La crearea unui nou proiect, IDE-ul CLion generează automat fişierul &amp;#039;&amp;#039;&amp;#039;main.cpp&amp;#039;&amp;#039;&amp;#039;. Acesta conţine un exemplu program ce va fi rescris de către utilizator. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Secţiunile marcate în imagine reprezintă:&lt;br /&gt;
# Zona &amp;lt;span style=&amp;quot;color: green&amp;quot;&amp;gt;verde&amp;lt;/span&amp;gt; - &amp;#039;&amp;#039;&amp;#039;Project view&amp;#039;&amp;#039;&amp;#039; indică toate fişierele şi directoarele ce alcătuiesc proiectul.&lt;br /&gt;
# Zona &amp;lt;span style=&amp;quot;color: blue&amp;quot;&amp;gt;albastră&amp;lt;/span&amp;gt; - &amp;#039;&amp;#039;&amp;#039;Editor&amp;#039;&amp;#039;&amp;#039; este fereastra de vizualizare şi editare a textului &lt;br /&gt;
# Zona &amp;lt;span style=&amp;quot;color: red&amp;quot;&amp;gt;roşie&amp;lt;/span&amp;gt; - &amp;#039;&amp;#039;&amp;#039;Toolbar&amp;#039;&amp;#039;&amp;#039; oferă acces rapid pentru operaţiile uzuale. Dintre acestea, cel mai des vom folosi:&lt;br /&gt;
#*&amp;#039;&amp;#039;&amp;#039;Build&amp;#039;&amp;#039;&amp;#039; [[Fișier:CLion_build_button.png | 16px]]&lt;br /&gt;
#*&amp;#039;&amp;#039;&amp;#039;Run&amp;#039;&amp;#039;&amp;#039; [[Fișier:CLion_run_button.png | 16px]]&lt;br /&gt;
#*&amp;#039;&amp;#039;&amp;#039;Debug&amp;#039;&amp;#039;&amp;#039; [[Fișier:CLion_debug_button.png | 16px]]&lt;br /&gt;
# Zona &amp;lt;span style=&amp;quot;color: gold&amp;quot;&amp;gt;galbenă&amp;lt;/span&amp;gt; - &amp;#039;&amp;#039;&amp;#039;Run&amp;#039;&amp;#039;&amp;#039; este zona în care se introduc datele de intrare şi se în care vor fi afişate datele de ieşire.&lt;br /&gt;
&lt;br /&gt;
== Exemplu de program în modul &amp;#039;&amp;#039;debug&amp;#039;&amp;#039; ==&lt;br /&gt;
&lt;br /&gt;
Copiați codul de mai jos înlocuind programul deja existent în fișierul &amp;#039;&amp;#039;main.c&amp;#039;&amp;#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
    printf(&amp;quot;Debugging program...\n&amp;quot;);&lt;br /&gt;
    int value = 0;&lt;br /&gt;
    value = value + 1;&lt;br /&gt;
    value++;&lt;br /&gt;
    value = value * 2;&lt;br /&gt;
    value -= 1;&lt;br /&gt;
    printf(&amp;quot;Value is now %d!\n&amp;quot;, value);&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pentru a executa programul în modul debug trebuie sa introducem cel puţin un &amp;#039;&amp;#039;&amp;#039;breakpoint&amp;#039;&amp;#039;&amp;#039;. Astfel indicăm programului unde se va opri pentru a ne acorda control asupra execuţiei, având posibilitatea de a continua execuţia pas cu pas. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Introducem un nou breakpoint dând click în dreptul liniei de la care vrem să obţinem controlul. În cazul nostru, vom alege să indroducem un breakpoint chiar la definirea variabilei &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Fișier:CLion_breakpoint.png | 1000px | Imaginea 4]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: red; font-weight: bold&amp;quot;&amp;gt;Atenție:&amp;lt;/span&amp;gt; Când alegem locaţia unui breakpoint trebuie să ţinem cont de următorul aspect: în modul &amp;#039;&amp;#039;&amp;#039;debug&amp;#039;&amp;#039;&amp;#039; programul se va opri &amp;#039;&amp;#039;&amp;#039;înainte&amp;#039;&amp;#039;&amp;#039; de a executa linia în dreptul căreia a fost introdus breakpoint-ul!&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În continuare, trebuie se pornim execuţia programului in modul debug [[Fișier:CLion_debug_button.png | 16px]]. Observăm apariţia ferestrei Debug (chenarul albastru, Imaginea 5) ce conţine următoarele:&lt;br /&gt;
#Zona &amp;lt;span style=&amp;quot;color: gold&amp;quot;&amp;gt;galbenă&amp;lt;/span&amp;gt; - fereastra cu toate variabilele declarate, împreună cu valorile lor. Momentan nu există nicio variabilă declarată (deoarece linia asupra la care ne-am oprit nu a fost încă executată!)&lt;br /&gt;
#Zona &amp;lt;span style=&amp;quot;color: red&amp;quot;&amp;gt;roşie&amp;lt;/span&amp;gt; - Permite trecerea între fereastra pentru procesul de depanare (&amp;#039;&amp;#039;&amp;#039;Debugger&amp;#039;&amp;#039;&amp;#039;) şi fereastra în care se afişează/introduc datele (&amp;#039;&amp;#039;&amp;#039;Console&amp;#039;&amp;#039;&amp;#039;)&lt;br /&gt;
#Zona &amp;lt;span style=&amp;quot;color: green&amp;quot;&amp;gt;verde&amp;lt;/span&amp;gt; - Conţine comenzile pentru controlul execuţiei în modul debug (comenzi numite &amp;#039;&amp;#039;&amp;#039;stepping actions&amp;#039;&amp;#039;&amp;#039;):&lt;br /&gt;
#*&amp;#039;&amp;#039;&amp;#039;Step over&amp;#039;&amp;#039;&amp;#039; [[Fișier:CLion_step_over.png | 16px]] - Execută comenzile de pe linia curentă şi trece la următoarea linie&lt;br /&gt;
#*&amp;#039;&amp;#039;&amp;#039;Step into&amp;#039;&amp;#039;&amp;#039; [[Fișier:CLion_step_into.png | 16px]] - Programul va executa linia curentă iar dacă pe linia curentă există un apel de funcție, se va opri pe prima linie din funcția respectivă. Această comandă este utilă atunci cand pe linia curentă se află un apel de funcţie şi vrem sa studiem comportamentul codului din interiorul funcţiei.&lt;br /&gt;
#*&amp;#039;&amp;#039;&amp;#039;Step out&amp;#039;&amp;#039;&amp;#039; [[Fișier:CLion_step_out.png | 16px]] - Termină de executat funcţia în care se află linia curentă&lt;br /&gt;
#*&amp;#039;&amp;#039;&amp;#039;Run to cursor&amp;#039;&amp;#039;&amp;#039; [[Fișier:CLion_run_to_cursor.png | 16px]] - Execută toate instructiunile până se intâlneste cursorul.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt; &amp;#039;&amp;#039;&amp;#039; Observație: &amp;#039;&amp;#039;&amp;#039; În modul debug, linia curentă este marcată de către mediul de dezvoltare prin colorarea acesteia cu albastru.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alte comenzi utile:&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Resume program&amp;#039;&amp;#039;&amp;#039; [[Fișier:CLion_resume_project.png | 16px]] - Continuă execuţia pâmă la următorul breakpoint (dacă nu există, se va executa până la final)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Stop&amp;#039;&amp;#039;&amp;#039; [[Fișier:CLion_stop.png | 16px]] - Se opreşte definitv execuţia programului, împreună cu modul debug&lt;br /&gt;
&lt;br /&gt;
[[Fișier:CLion_debug_process.png | 1000px | Imaginea 5]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pentru a exersa utilizarea sistemului de debug, realizați următoarele operații:&lt;br /&gt;
# Parcurgeti tot programul folosind &amp;#039;&amp;#039;&amp;#039;Step Over&amp;#039;&amp;#039;&amp;#039; și vizualizând valoarea variabilei &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt; la fiecare pas, până la ultima linie din program, unde utilizați &amp;#039;&amp;#039;&amp;#039;Resume program&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
# Reporniți aplicația în modul de debug și puneți un al doilea &amp;#039;&amp;#039;breakpoint&amp;#039;&amp;#039; pe linia cu apelul funcției &amp;lt;code&amp;gt;printf&amp;lt;/code&amp;gt;. &lt;br /&gt;
# Folosiți &amp;#039;&amp;#039;&amp;#039;Resume program&amp;#039;&amp;#039;&amp;#039; pentru a ajunge la al doilea &amp;#039;&amp;#039;breakpoint&amp;#039;&amp;#039;.&lt;br /&gt;
# Odată ajunși acolo, folosiți &amp;#039;&amp;#039;&amp;#039;Step In&amp;#039;&amp;#039;&amp;#039; pentru a intra în funcția &amp;lt;code&amp;gt;printf&amp;lt;/code&amp;gt; (neavând codul sursă, veți vedea codul de asamblare obținut din dezasamblarea fișierului obiect de către GDB).&lt;br /&gt;
# Folosiți &amp;#039;&amp;#039;&amp;#039;Step Out&amp;#039;&amp;#039;&amp;#039; pentru a reveni în funcția &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; și apoi &amp;#039;&amp;#039;&amp;#039;Resume program&amp;#039;&amp;#039;&amp;#039; pentru a termina execuția.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips &amp;amp; Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== Formatare automată a codului ===&lt;br /&gt;
&lt;br /&gt;
CLion oferă opțiunea de a formata automat codul prin selectarea &amp;#039;&amp;#039;&amp;#039;Code -&amp;gt; Reformat Code&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
Ce probleme rezolvă această formatare automată:&lt;br /&gt;
* alinierea liniilor în funcție de blocurile de instrucțiuni și tipurile de &amp;#039;&amp;#039;statements&amp;#039;&amp;#039; de pe fiecare linie;&lt;br /&gt;
* plasarea sau eliminarea de spații acolo unde este necasar.&lt;br /&gt;
Ce probleme NU rezolvă această formatare automată;&lt;br /&gt;
* lipsa acoladelor de la blocurile &amp;#039;&amp;#039;&amp;#039;if&amp;#039;&amp;#039;&amp;#039; și &amp;#039;&amp;#039;&amp;#039;for&amp;#039;&amp;#039;&amp;#039;;&lt;br /&gt;
* numele insuficient de sugestive pentru numele de funcții, structuri sau variabile.&lt;br /&gt;
&lt;br /&gt;
Stilul conform căruia este modificat codul poate fi configurat folosind meniul &amp;lt;code&amp;gt;File|Settings|Editor|CodeStyle&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generare automată a codului ===&lt;br /&gt;
&lt;br /&gt;
CLion oferă posibilitatea de a genera fragmente de cod des înâlnite, precum constructori şi operatori în interiorul claselor. Această acţiune poate fi realizată folosind meniul &amp;lt;code&amp;gt; Code|Generate&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Altele ===&lt;br /&gt;
* [https://www.jetbrains.com/help/clion/using-todo.html TODO Comments]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt; Nu uitați de regulile următoare: [[Convenții de cod - C]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
= Exerciții =&lt;br /&gt;
&lt;br /&gt;
*Săptămâna 1&lt;br /&gt;
*# Realizați un proiect nou în Netbeans și scrieți un program care să citească de la tastatură un număr întreg fără semn &amp;lt;code&amp;gt;size&amp;lt;/code&amp;gt;. Se va aloca apoi dinamic în HEAP un vector de &amp;lt;code&amp;gt;size&amp;lt;/code&amp;gt; valori numerice întregi pe 16 biți. Scrieți o funcție care să citească &amp;lt;code&amp;gt;size&amp;lt;/code&amp;gt; valori de la tastatură și să le plaseze în vector. Scrieți apoi o funcție care să găsească valoarea maximă din vector. Apelați în &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; funcțiile de mai sus și afișați valoarea obținută pe ecran. Nu uitați să dezalocați memoria alocată. Pentru funcțiile de alocare și dezalocare de memorie, puteți recapitula [[PC Laborator 12]].&lt;br /&gt;
*# Modificați programul de mai sus astfel încât citirea variabilei &amp;lt;code&amp;gt;size&amp;lt;/code&amp;gt; cât și alocarea de memorie să fie făcută într-o funcție separată. Această funcție trebuie să întoarcă un pointer cu adresa de început a vectorului dar și dimensiunea acestuia.&lt;br /&gt;
*# Realizați un alt proiect în Netbeans și scrieți un program care să citească de la tastatură un șir de caractere de lungime maximă 255. Folosind aritmetica pointerilor și o singură buclă &amp;#039;&amp;#039;&amp;#039;for&amp;#039;&amp;#039;&amp;#039;, afișați pe ecran doar cifrele din șirul citit.&lt;br /&gt;
* Săptămâna 2&lt;br /&gt;
*# Realizați un proiect nou în Netbeans și scrieți un program care să citească de la tastatură un număr întreg fără semn &amp;lt;code&amp;gt;size&amp;lt;/code&amp;gt;. Scrieți apoi o funcție care să aloce memorie pentru un șir de caractere care să conțină de &amp;lt;code&amp;gt;size&amp;lt;/code&amp;gt; ori secvența &amp;quot;ha&amp;quot; (spre exemplu, pentru size == 3, string-ul va trebui să conțină &amp;quot;hahaha&amp;quot;), să umple șirul cu numărul cerut de &amp;quot;ha&amp;quot;-uri și să întoarcă adresa memoriei alocate. În funcția &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; afișați șirul de caractere (nu uitați la alocare de terminatorul de sfârșit de șir). Nu uitați să dezalocați memoria. Pentru funcțiile de alocare și dezalocare de memorie, puteți recapitula [[PC Laborator 12]].&lt;br /&gt;
*# Modificați programul de mai sus astfel încât în loc de secvența &amp;quot;ha&amp;quot;, secvența repetată să fie citită de la tastatură cu &amp;lt;code&amp;gt;scanf&amp;lt;/code&amp;gt; și trimisă ca argument funcției de alocare. &lt;br /&gt;
*# Realizați un alt proiect în Netbeans și scrieți un program care să citească de la tastatură un șir de caractere de lungime maximă 255. Scrieți o singură funcție care să numere și să întoarcă numărul de litere și numărul de cifre din șirul citit. Aceste valori se vor afișa pe ecran în funcția &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt;.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Probleme propuse =&lt;br /&gt;
&lt;br /&gt;
Problemele de mai jos au anumite erori care trebuie gasite si raparate folosind debugger-ul.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Problema 1 ==&lt;br /&gt;
Programul de mai jos ar trebui să citească de la tastatură un șir de maxim 1024 caractere și să afișeze câte litere mici, câte litere mari și câte cifre conține acest șir. Totuși acest program are o eroare. Folosiți debugger-ul pentru a o identifica și repara.&lt;br /&gt;
&lt;br /&gt;
Exemplu de intrare:&lt;br /&gt;
&lt;br /&gt;
Ana a plecat la piata si a cumparat 10 saci de cartofi.&lt;br /&gt;
&lt;br /&gt;
Ieșirea pentru intrarea de mai sus:&lt;br /&gt;
&lt;br /&gt;
40 1 2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    char c;&lt;br /&gt;
    unsigned uppercaseChars = 0;&lt;br /&gt;
    unsigned lowecaseChars = 0;    &lt;br /&gt;
    unsigned digits = 0;&lt;br /&gt;
    &lt;br /&gt;
    while(scanf(&amp;quot;%c&amp;quot;, c) != EOF) {&lt;br /&gt;
        if(c &amp;gt; &amp;#039;a&amp;#039; || c &amp;lt; &amp;#039;z&amp;#039;) {&lt;br /&gt;
            lowecaseChars++;&lt;br /&gt;
        } else if(c &amp;gt; &amp;#039;A&amp;#039; &amp;amp;&amp;amp; c &amp;lt; &amp;#039;Z&amp;#039;) {&lt;br /&gt;
            uppercaseChars++;&lt;br /&gt;
        } else {&lt;br /&gt;
            digits++;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;%u %u %u&amp;quot;, lowecaseChars, uppercaseChars, digits);&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Problema 2 ==&lt;br /&gt;
Un tehnician a măsurat un număr mare n de rezistori şi a obţinut n valori de rezistenţe. Tehnicianul ştie că rezistorii sunt de acelaşi fel, dar pentru că sunt vechi şi codul culorilor nu mai este vizibil, doreşte să calculeze valoarea nominală a rezistenţei (R) şi dispersia valorilor, (S). Apoi, având aceste valori, el vrea să determine câte din rezistenţele testate (procentual) se încadrează în intervalul [R – S; R + S]. Rezistenţa nominală se calculează ca media aritmetică a valorilor rezistenţelor, iar formula dispersiei este dată mai jos.&lt;br /&gt;
&lt;br /&gt;
Cerinţă&lt;br /&gt;
Dându-se un număr n de rezistori şi valorile rezistenţelor acestora Ri (i = 1, ..., n), să se determine procentul rezistoarelor care au rezistenţa în intervalul [R– S; R + S].&lt;br /&gt;
&lt;br /&gt;
Date de intrare&lt;br /&gt;
Pe prima linie se află numărul întreg n. Pe următoarea linie, separate printr-un spaţiu, sunt n valori fracţionare de rezistenţe (în ohmi).&lt;br /&gt;
&lt;br /&gt;
Date de ieşire&lt;br /&gt;
Se va afişa o singură valoare fracţionară, cu exact două zecimale reprezentând procentul de rezistori cu rezistenţa în intervalul [R – S; R + S].&lt;br /&gt;
&lt;br /&gt;
Restricţii şi precizări:&lt;br /&gt;
&lt;br /&gt;
1 &amp;lt; n &amp;lt; 1000&lt;br /&gt;
&lt;br /&gt;
1.0 &amp;lt;= Ri &amp;lt;= 10000.0 &lt;br /&gt;
&lt;br /&gt;
S=sqrt( pow(sum(R[i]−R),2) / n )&lt;br /&gt;
&lt;br /&gt;
Exemplu:&lt;br /&gt;
&lt;br /&gt;
Input =&lt;br /&gt;
10&lt;br /&gt;
&lt;br /&gt;
76 1 20 37 19 92 61 96 37 77&lt;br /&gt;
&lt;br /&gt;
Output = &lt;br /&gt;
50.00&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;vector&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;unordered_map&amp;gt;&lt;br /&gt;
#include &amp;lt;algorithm&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    int n;&lt;br /&gt;
    double values[n];&lt;br /&gt;
    scanf(&amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
    int sum = 0;&lt;br /&gt;
    for(int i = 0; i &amp;lt; n; i++){&lt;br /&gt;
        scanf(&amp;quot;%lf&amp;quot;, &amp;amp;values[i]);&lt;br /&gt;
        sum += values[i];&lt;br /&gt;
    }&lt;br /&gt;
    double average = sum / n;&lt;br /&gt;
    double dispersion = 0;&lt;br /&gt;
    for(int i = 0; i &amp;lt; n; i++){&lt;br /&gt;
        dispersion += (values[i] - average) * (values[i] - average);&lt;br /&gt;
    }&lt;br /&gt;
    dispersion = sqrt(dispersion / n);&lt;br /&gt;
    int larger = 0;&lt;br /&gt;
    for(int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
        if(values[i] &amp;gt;= average - dispersion &lt;br /&gt;
                &amp;amp;&amp;amp; values[i] &amp;lt;= average + dispersion) larger++;&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;%.2lf&amp;quot;, 100 * larger / n);&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Problema 3 ==&lt;br /&gt;
Sunteți angajați de ministerul învățamântului să scrieți un program care să listeze toți elevii care au promovat examenul de bacalaureat. De la tastatură se introduce un număr n reprezentând numărul de candidați, apoi pe următoarele n linii, un nume de elev (format din exact două cuvinte: nume și prenume) și notele la cele patru materii, format fracționar, valori între 1 și 10. Să se afișeze toți studenții care au promovat examenul de bacalaureat (media mai mare ca 6, fiecare notă mai mare ca 5) în ordinea inversă a introducerii lor, împreună cu media de promovare, afișată cu fix două zecimale.&lt;br /&gt;
&lt;br /&gt;
Exemplu de date de intrare:&lt;br /&gt;
&lt;br /&gt;
4&lt;br /&gt;
&lt;br /&gt;
Gheorghe Ghita 8 7 5.5 10&lt;br /&gt;
&lt;br /&gt;
Vuia Vasile 4 10 10 10&lt;br /&gt;
&lt;br /&gt;
Andreescu Andra 9 10 9 10&lt;br /&gt;
&lt;br /&gt;
Elenescu Elena 5 5 5 5&lt;br /&gt;
&lt;br /&gt;
Ieșirea pentru intrarea de mai sus:&lt;br /&gt;
&lt;br /&gt;
Andreescu Andra 9.50&lt;br /&gt;
&lt;br /&gt;
Gheorghe Ghita 7.63&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
struct studenti{&lt;br /&gt;
char n[128];&lt;br /&gt;
char m[128];&lt;br /&gt;
float a,b,c,d;&lt;br /&gt;
};&lt;br /&gt;
int main(){&lt;br /&gt;
int n,i;&lt;br /&gt;
struct studenti s[n];&lt;br /&gt;
scanf(&amp;quot;%d&amp;quot;, &amp;amp;n);&lt;br /&gt;
for(i=0;i&amp;lt;n;i++)&lt;br /&gt;
scanf(&amp;quot;%s%s%f%f%f%f&amp;quot;,&amp;amp;s[i].n,&amp;amp;s[i].m,&amp;amp;s[i].a,&amp;amp;s[i].b,&amp;amp;s[i].c,&amp;amp;s[i].d);&lt;br /&gt;
&lt;br /&gt;
for(i=n;i&amp;gt;0;i--){&lt;br /&gt;
float m=(s[i].a+s[i].b+s[i].c+s[i].d)/4;&lt;br /&gt;
if(s[i].a&amp;gt;5&amp;amp;&amp;amp;s[i].b&amp;gt;5&amp;amp;&amp;amp;s[i].c&amp;gt;5&amp;amp;&amp;amp;s[i].d&amp;gt;5||m&amp;gt;=6){&lt;br /&gt;
printf(&amp;quot;%s %s %.2f\n&amp;quot;,s[i].n,s[i].m,m);&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=Colocviu_pclp1&amp;diff=7587</id>
		<title>Colocviu pclp1</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=Colocviu_pclp1&amp;diff=7587"/>
		<updated>2024-09-07T12:01:51Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Cerință =&lt;br /&gt;
&lt;br /&gt;
­­­Sunteți la ora de matematică și tocmai ați învățat despre vectori și matrici. Pentru că întotdeauna v-au pasionat calculatoarele, ați reușit să învățați informatica de bază de timpuriu și, de asemenea, să asimilați cunoștințe despre matrici și vectori prin intermediul ei. Vi s-a dat o temă la matematică și, pentru a vă ușura munca, ați decis să scrieți un program care să rezolve cerințele din temă.&lt;br /&gt;
&lt;br /&gt;
Tema este următoarea:&lt;br /&gt;
&lt;br /&gt;
Aveți un șir de numere întregi. Pentru acest șir vi se cer următoarele:&lt;br /&gt;
&lt;br /&gt;
# &amp;#039;&amp;#039;(6p)&amp;#039;&amp;#039; Pentru fiecare trei numere consecutive din șir calculați media lor aritmetică și afișați mediile, separate cu câte un spațiu între ele. Pentru ușurință se va afișa un spațiu și după ultima medie. Acestea vor fi afișate ca numere fracționare, cu două zecimale după virgulă.&lt;br /&gt;
# &amp;#039;&amp;#039;(6p)&amp;#039;&amp;#039; Pentru mediile calculate anterior, găsiți maximul dintre ele și afișați-l, tot cu 2 zecimale după virgulă.&lt;br /&gt;
# &amp;#039;&amp;#039;(6p)&amp;#039;&amp;#039; Cu numerele pozitive (mai mari strict ca 0) și pare, vi se cere să formați un nou șir de numere și să calculați mediile aritmetice, de data aceasta pentru câte două numere. Numerele folosite pentru medii vor fi: primul cu ultimul, al doilea cu penultimul și tot așa. Dacă numărul de numere din noul șir este impar, numărul din mijloc va reprezenta el singur una dintre medii. Afișați maximul dintre aceste medii nou obținute, de asemenea cu 2 zecimale după virgulă.&lt;br /&gt;
# &amp;#039;&amp;#039;(6p)&amp;#039;&amp;#039; Pentru șirul de numere inițiale, vi se cere să formați cea mai mare matrice pătratică care se poate realiza cu numerele din șir și să o afișați. Numerele vor fi separate pe fiecare linie cu câte un spațiu și, pentru ușurință, se va afișa un spațiu și după ultimul element de pe o linie. Toate liniile se vor termina cu un caracter newline.&lt;br /&gt;
# &amp;#039;&amp;#039;(6p)&amp;#039;&amp;#039; La acest subpunct vi se garantează că matricea pătratică obținută conține doar numere de o cifră. Voi trebuie să formați câte un număr pentru fiecare coloană din matrice. Numerele se formează prin alipirea respectivelor cifre, începând cu cea de pe prima linie și terminând cu cifra de pe ultima linie. Dintre numerele astfel obținute, afisați doar numerele prime, cu câte un spațiu între ele. Pentru ușurință, se va afișa un spațiu și după ultimul număr.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Datele de intrare vor fi, pentru fiecare subpunct, de forma:&lt;br /&gt;
&lt;br /&gt;
    numar_elemente&lt;br /&gt;
    elementele din sir separate cu un spatiu&lt;br /&gt;
    litera_subpunct&lt;br /&gt;
&lt;br /&gt;
unde pentru subpunctul 1, litera_subpunct este a, pentru 2: b, ș.a.m.d.&lt;br /&gt;
&lt;br /&gt;
= Exemple =&lt;br /&gt;
&lt;br /&gt;
== Intrare ==&lt;br /&gt;
&lt;br /&gt;
    10&lt;br /&gt;
    7 15 2 8 4 9 1 1 1 5          &lt;br /&gt;
    a&lt;br /&gt;
&lt;br /&gt;
== Ieșire ==&lt;br /&gt;
&lt;br /&gt;
    8.00 8.33 4.67 7.00 4.67 3.67 1.00 2.33    &lt;br /&gt;
&lt;br /&gt;
== Explicații ==&lt;br /&gt;
&lt;br /&gt;
Media primelor trei numere este (7 + 15 + 2) / 3 = 8.00, a următoarelor trei numere: (15 + 2 + 8) / 3 = 8.33 etc.&lt;br /&gt;
&lt;br /&gt;
== Intrare ==&lt;br /&gt;
&lt;br /&gt;
    10&lt;br /&gt;
    7 15 2 8 4 9 1 1 1 5&lt;br /&gt;
    b      &lt;br /&gt;
&lt;br /&gt;
== Ieșire ==&lt;br /&gt;
&lt;br /&gt;
    8.33&lt;br /&gt;
&lt;br /&gt;
== Explicații ==&lt;br /&gt;
&lt;br /&gt;
Mediile sunt: 8.00, 8.33, 4.67, 7.00, 4.67, 3.67, 1.00, respectiv 2.33, maximul dintre ele fiind 8.33.&lt;br /&gt;
&lt;br /&gt;
== Intrare ==&lt;br /&gt;
&lt;br /&gt;
    16&lt;br /&gt;
    7 15 -2 8 2 -4 9 1 1 1 5 4 6 6 -8 3                             &lt;br /&gt;
    c  &lt;br /&gt;
&lt;br /&gt;
== Ieșire ==&lt;br /&gt;
&lt;br /&gt;
    7.00&lt;br /&gt;
&lt;br /&gt;
== Explicații ==&lt;br /&gt;
&lt;br /&gt;
Șirul nou format din numerele pare și pozitive este: 8, 2, 4, 6, 6. Mediile vor fi: (8 + 6) / 2 = 7, (2 + 6) / 2 = 4 și 4 (doarece numărul numerelor este impar). Cea mai mare valoare dintre acestea trei este 7.00.&lt;br /&gt;
&lt;br /&gt;
== Intrare ==&lt;br /&gt;
&lt;br /&gt;
    10&lt;br /&gt;
    7 15 2 8 4 9 1 1 1 5&lt;br /&gt;
    d &lt;br /&gt;
&lt;br /&gt;
== Ieșire ==&lt;br /&gt;
&lt;br /&gt;
    7 15 2&lt;br /&gt;
    8 4 9&lt;br /&gt;
    1 1 1&lt;br /&gt;
&lt;br /&gt;
== Explicații ==&lt;br /&gt;
&lt;br /&gt;
Avem 10 numere în șir, deci cea mai mare matrice pătratică va fi formată din primele 9 numere deoarece 9 este cel mai apropiat pătrat perfect mai mic decât 10.&lt;br /&gt;
&lt;br /&gt;
== Intrare ==&lt;br /&gt;
&lt;br /&gt;
    10&lt;br /&gt;
    1 2 3 3 5 6 7 8 7 1&lt;br /&gt;
    e&lt;br /&gt;
&lt;br /&gt;
== Ieșire ==&lt;br /&gt;
&lt;br /&gt;
    137 367 &lt;br /&gt;
&lt;br /&gt;
== Explicații ==&lt;br /&gt;
&lt;br /&gt;
Matricea formată va fi:&lt;br /&gt;
&lt;br /&gt;
1 2 3&lt;br /&gt;
3 5 6&lt;br /&gt;
7 8 7&lt;br /&gt;
&lt;br /&gt;
Numerele rezultate prin alipirea cifrelor de pe fiecare coloană vor fi 137, 258 și 367, dintre care 137 și 367 sunt numere prime și ele vor fi afișate.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=Colocviu_pclp1&amp;diff=7586</id>
		<title>Colocviu pclp1</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=Colocviu_pclp1&amp;diff=7586"/>
		<updated>2024-09-07T12:01:25Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Cerință =&lt;br /&gt;
&lt;br /&gt;
­­­Sunteți la ora de matematică și tocmai ați învățat despre vectori și matrici. Pentru că întotdeauna v-au pasionat calculatoarele, ați reușit să învățați informatica de bază de timpuriu și, de asemenea, să asimilați cunoștințe despre matrici și vectori prin intermediul ei. Vi s-a dat o temă la matematică și, pentru a vă ușura munca, ați decis să scrieți un program care să rezolve cerințele din temă.&lt;br /&gt;
&lt;br /&gt;
Tema este următoarea:&lt;br /&gt;
&lt;br /&gt;
Aveți un șir de numere întregi. Pentru acest șir vi se cer următoarele:&lt;br /&gt;
&lt;br /&gt;
# &amp;#039;&amp;#039;(6p)&amp;#039;&amp;#039; Pentru fiecare trei numere consecutive din șir calculați media lor aritmetică și afișați mediile, separate cu câte un spațiu între ele. Pentru ușurință se va afișa un spațiu și după ultima medie. Acestea vor fi afișate ca numere fracționare, cu două zecimale după virgulă.&lt;br /&gt;
# &amp;#039;&amp;#039;(6p)&amp;#039;&amp;#039; Pentru mediile calculate anterior, găsiți maximul dintre ele și afișați-l, tot cu 2 zecimale după virgulă.&lt;br /&gt;
# &amp;#039;&amp;#039;(6p)&amp;#039;&amp;#039; Cu numerele pozitive (mai mari strict ca 0) și pare, vi se cere să formați un nou șir de numere și să calculați mediile aritmetice, de data aceasta pentru câte două numere. Numerele folosite pentru medii vor fi: primul cu ultimul, al doilea cu penultimul și tot așa. Dacă numărul de numere din noul șir este impar, numărul din mijloc va reprezenta el singur una dintre medii. Afișați maximul dintre aceste medii nou obținute, de asemenea cu 2 zecimale după virgulă.&lt;br /&gt;
# &amp;#039;&amp;#039;(6p)&amp;#039;&amp;#039; Pentru șirul de numere inițiale, vi se cere să formați cea mai mare matrice pătratică care se poate realiza cu numerele din șir și să o afișați. Numerele vor fi separate pe fiecare linie cu câte un spațiu și, pentru ușurință, se va afișa un spațiu și după ultimul element de pe o linie. Toate liniile se vor termina cu un caracter newline.&lt;br /&gt;
# &amp;#039;&amp;#039;(6p)&amp;#039;&amp;#039; La acest subpunct vi se garantează că matricea pătratică obținută conține doar numere de o cifră. Voi trebuie să formați câte un număr pentru fiecare coloană din matrice. Numerele se formează prin alipirea respectivelor cifre, începând cu cea de pe prima linie și terminând cu cifra de pe ultima linie. Dintre numerele astfel obținute, afisați doar numerele prime, cu câte un spațiu între ele. Pentru ușurință, se va afișa un spațiu și după ultimul număr.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Datele de intrare vor fi, pentru fiecare subpunct, de forma:&lt;br /&gt;
&lt;br /&gt;
    numar_elemente&lt;br /&gt;
    elementele din sir separate cu un spatiu&lt;br /&gt;
    litera_subpunct&lt;br /&gt;
&lt;br /&gt;
unde pentru subpunctul 1, litera_subpunct este a, pentru 2: b, ș.a.m.d.&lt;br /&gt;
&lt;br /&gt;
= Exemple =&lt;br /&gt;
&lt;br /&gt;
== Intrare ==&lt;br /&gt;
&lt;br /&gt;
    10&lt;br /&gt;
    7 15 2 8 4 9 1 1 1 5          &lt;br /&gt;
    a&lt;br /&gt;
&lt;br /&gt;
== Ieșire ==&lt;br /&gt;
&lt;br /&gt;
    8.00 8.33 4.67 7.00 4.67 3.67 1.00 2.33    &lt;br /&gt;
&lt;br /&gt;
== Explicații&lt;br /&gt;
&lt;br /&gt;
Media primelor trei numere este (7 + 15 + 2) / 3 = 8.00, a următoarelor trei numere: (15 + 2 + 8) / 3 = 8.33 etc.&lt;br /&gt;
&lt;br /&gt;
== Intrare ==&lt;br /&gt;
&lt;br /&gt;
    10&lt;br /&gt;
    7 15 2 8 4 9 1 1 1 5&lt;br /&gt;
    b      &lt;br /&gt;
&lt;br /&gt;
== Ieșire ==&lt;br /&gt;
&lt;br /&gt;
    8.33&lt;br /&gt;
&lt;br /&gt;
== Explicații ==&lt;br /&gt;
&lt;br /&gt;
Mediile sunt: 8.00, 8.33, 4.67, 7.00, 4.67, 3.67, 1.00, respectiv 2.33, maximul dintre ele fiind 8.33.&lt;br /&gt;
&lt;br /&gt;
== Intrare ==&lt;br /&gt;
&lt;br /&gt;
    16&lt;br /&gt;
    7 15 -2 8 2 -4 9 1 1 1 5 4 6 6 -8 3                             &lt;br /&gt;
    c  &lt;br /&gt;
&lt;br /&gt;
== Ieșire ==&lt;br /&gt;
&lt;br /&gt;
    7.00&lt;br /&gt;
&lt;br /&gt;
== Explicații ==&lt;br /&gt;
&lt;br /&gt;
Șirul nou format din numerele pare și pozitive este: 8, 2, 4, 6, 6. Mediile vor fi: (8 + 6) / 2 = 7, (2 + 6) / 2 = 4 și 4 (doarece numărul numerelor este impar). Cea mai mare valoare dintre acestea trei este 7.00.&lt;br /&gt;
&lt;br /&gt;
== Intrare ==&lt;br /&gt;
&lt;br /&gt;
    10&lt;br /&gt;
    7 15 2 8 4 9 1 1 1 5&lt;br /&gt;
    d &lt;br /&gt;
&lt;br /&gt;
== Ieșire ==&lt;br /&gt;
&lt;br /&gt;
    7 15 2&lt;br /&gt;
    8 4 9&lt;br /&gt;
    1 1 1&lt;br /&gt;
&lt;br /&gt;
== Explicații ==&lt;br /&gt;
&lt;br /&gt;
Avem 10 numere în șir, deci cea mai mare matrice pătratică va fi formată din primele 9 numere deoarece 9 este cel mai apropiat pătrat perfect mai mic decât 10.&lt;br /&gt;
&lt;br /&gt;
== Intrare ==&lt;br /&gt;
&lt;br /&gt;
    10&lt;br /&gt;
    1 2 3 3 5 6 7 8 7 1&lt;br /&gt;
    e&lt;br /&gt;
&lt;br /&gt;
== Ieșire ==&lt;br /&gt;
&lt;br /&gt;
    137 367 &lt;br /&gt;
&lt;br /&gt;
== Explicații ==&lt;br /&gt;
&lt;br /&gt;
Matricea formată va fi:&lt;br /&gt;
&lt;br /&gt;
1 2 3&lt;br /&gt;
3 5 6&lt;br /&gt;
7 8 7&lt;br /&gt;
&lt;br /&gt;
Numerele rezultate prin alipirea cifrelor de pe fiecare coloană vor fi 137, 258 și 367, dintre care 137 și 367 sunt numere prime și ele vor fi afișate.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=Colocviu_pclp1&amp;diff=7585</id>
		<title>Colocviu pclp1</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=Colocviu_pclp1&amp;diff=7585"/>
		<updated>2024-09-07T11:58:48Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: Pagină nouă: ­­­Sunteți la ora de matematică și tocmai ați învățat despre vectori și matrici. Pentru că întotdeauna v-au pasionat calculatoarele, ați reușit să învățați info...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;­­­Sunteți la ora de matematică și tocmai ați învățat despre vectori și matrici. Pentru că întotdeauna v-au pasionat calculatoarele, ați reușit să învățați informatica de bază de timpuriu și, de asemenea, să asimilați cunoștințe despre matrici și vectori prin intermediul ei. Vi s-a dat o temă la matematică și, pentru a vă ușura munca, ați decis să scrieți un program care să rezolve cerințele din temă.&lt;br /&gt;
&lt;br /&gt;
Tema este următoarea:&lt;br /&gt;
&lt;br /&gt;
Aveți un șir de numere întregi. Pentru acest șir vi se cer următoarele:&lt;br /&gt;
&lt;br /&gt;
# &amp;#039;&amp;#039;(6p)&amp;#039;&amp;#039; Pentru fiecare trei numere consecutive din șir calculați media lor aritmetică și afișați mediile, separate cu câte un spațiu între ele. Pentru ușurință se va afișa un spațiu și după ultima medie. Acestea vor fi afișate ca numere fracționare, cu două zecimale după virgulă.&lt;br /&gt;
# &amp;#039;&amp;#039;(6p)&amp;#039;&amp;#039; Pentru mediile calculate anterior, găsiți maximul dintre ele și afișați-l, tot cu 2 zecimale după virgulă.&lt;br /&gt;
# &amp;#039;&amp;#039;(6p)&amp;#039;&amp;#039; Cu numerele pozitive (mai mari strict ca 0) și pare, vi se cere să formați un nou șir de numere și să calculați mediile aritmetice, de data aceasta pentru câte două numere. Numerele folosite pentru medii vor fi: primul cu ultimul, al doilea cu penultimul și tot așa. Dacă numărul de numere din noul șir este impar, numărul din mijloc va reprezenta el singur una dintre medii. Afișați maximul dintre aceste medii nou obținute, de asemenea cu 2 zecimale după virgulă.&lt;br /&gt;
# &amp;#039;&amp;#039;(6p)&amp;#039;&amp;#039; Pentru șirul de numere inițiale, vi se cere să formați cea mai mare matrice pătratică care se poate realiza cu numerele din șir și să o afișați. Numerele vor fi separate pe fiecare linie cu câte un spațiu și, pentru ușurință, se va afișa un spațiu și după ultimul element de pe o linie. Toate liniile se vor termina cu un caracter newline.&lt;br /&gt;
# &amp;#039;&amp;#039;(6p)&amp;#039;&amp;#039; La acest subpunct vi se garantează că matricea pătratică obținută conține doar numere de o cifră. Voi trebuie să formați câte un număr pentru fiecare coloană din matrice. Numerele se formează prin alipirea respectivelor cifre, începând cu cea de pe prima linie și terminând cu cifra de pe ultima linie. Dintre numerele astfel obținute, afisați doar numerele prime, cu câte un spațiu între ele. Pentru ușurință, se va afișa un spațiu și după ultimul număr.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Datele de intrare vor fi, pentru fiecare subpunct, de forma:&lt;br /&gt;
&lt;br /&gt;
    numar_elemente&lt;br /&gt;
    elementele din sir separate cu un spatiu&lt;br /&gt;
    litera_subpunct&lt;br /&gt;
&lt;br /&gt;
unde pentru subpunctul 1, litera_subpunct este a, pentru 2: b, ș.a.m.d.&lt;br /&gt;
&lt;br /&gt;
= Exemple =&lt;br /&gt;
&lt;br /&gt;
== Intrare ==&lt;br /&gt;
&lt;br /&gt;
    10&lt;br /&gt;
    7 15 2 8 4 9 1 1 1 5          &lt;br /&gt;
    a&lt;br /&gt;
&lt;br /&gt;
== Ieșire ==&lt;br /&gt;
&lt;br /&gt;
    8.00 8.33 4.67 7.00 4.67 3.67 1.00 2.33    &lt;br /&gt;
&lt;br /&gt;
== Explicații&lt;br /&gt;
&lt;br /&gt;
Media primelor trei numere este (7 + 15 + 2) / 3 = 8.00, a următoarelor trei numere: (15 + 2 + 8) / 3 = 8.33 etc.&lt;br /&gt;
&lt;br /&gt;
== Intrare ==&lt;br /&gt;
&lt;br /&gt;
    10&lt;br /&gt;
    7 15 2 8 4 9 1 1 1 5&lt;br /&gt;
    b      &lt;br /&gt;
&lt;br /&gt;
== Ieșire ==&lt;br /&gt;
&lt;br /&gt;
    8.33&lt;br /&gt;
&lt;br /&gt;
== Explicații&lt;br /&gt;
&lt;br /&gt;
Mediile sunt: 8.00, 8.33, 4.67, 7.00, 4.67, 3.67, 1.00, respectiv 2.33, maximul dintre ele fiind 8.33.&lt;br /&gt;
&lt;br /&gt;
== Intrare ==&lt;br /&gt;
&lt;br /&gt;
    16&lt;br /&gt;
    7 15 -2 8 2 -4 9 1 1 1 5 4 6 6 -8 3                             &lt;br /&gt;
    c  &lt;br /&gt;
&lt;br /&gt;
== Ieșire ==&lt;br /&gt;
&lt;br /&gt;
    7.00&lt;br /&gt;
&lt;br /&gt;
== Explicații&lt;br /&gt;
&lt;br /&gt;
Șirul nou format din numerele pare și pozitive este: 8, 2, 4, 6, 6. Mediile vor fi: (8 + 6) / 2 = 7, (2 + 6) / 2 = 4 și 4 (doarece numărul numerelor este impar). Cea mai mare valoare dintre acestea trei este 7.00.&lt;br /&gt;
&lt;br /&gt;
== Intrare ==&lt;br /&gt;
&lt;br /&gt;
    10&lt;br /&gt;
    7 15 2 8 4 9 1 1 1 5&lt;br /&gt;
    d &lt;br /&gt;
&lt;br /&gt;
== Ieșire ==&lt;br /&gt;
&lt;br /&gt;
    7 15 2&lt;br /&gt;
    8 4 9&lt;br /&gt;
    1 1 1&lt;br /&gt;
&lt;br /&gt;
== Explicații&lt;br /&gt;
&lt;br /&gt;
Avem 10 numere în șir, deci cea mai mare matrice pătratică va fi formată din primele 9 numere deoarece 9 este cel mai apropiat pătrat perfect mai mic decât 10.&lt;br /&gt;
&lt;br /&gt;
== Intrare ==&lt;br /&gt;
&lt;br /&gt;
    10&lt;br /&gt;
    1 2 3 3 5 6 7 8 7 1&lt;br /&gt;
    e&lt;br /&gt;
&lt;br /&gt;
== Ieșire ==&lt;br /&gt;
&lt;br /&gt;
    137 367 &lt;br /&gt;
&lt;br /&gt;
== Explicații&lt;br /&gt;
&lt;br /&gt;
Matricea formată va fi:&lt;br /&gt;
&lt;br /&gt;
1 2 3&lt;br /&gt;
3 5 6&lt;br /&gt;
7 8 7&lt;br /&gt;
&lt;br /&gt;
Numerele rezultate prin alipirea cifrelor de pe fiecare coloană vor fi 137, 258 și 367, dintre care 137 și 367 sunt numere prime și ele vor fi afișate.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=PC_Laborator_8&amp;diff=7429</id>
		<title>PC Laborator 8</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=PC_Laborator_8&amp;diff=7429"/>
		<updated>2023-01-29T09:36:27Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Căutarea unui caracter într-un șir de caractere */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Obiective == &lt;br /&gt;
  &lt;br /&gt;
în urma acestui laborator, studentul va fi capabil să: &lt;br /&gt;
*înțeleagă cum funcționează șirurile de caractere &lt;br /&gt;
*facă operații cu șiruri de caractere&lt;br /&gt;
&lt;br /&gt;
== Șiruri de caractere == &lt;br /&gt;
&lt;br /&gt;
[[Fișier:ascii_table.jpg|thumb]]&lt;br /&gt;
&lt;br /&gt;
În C, tipul de dată șir nu există în mod implicit. Singurul mod prin care putem opera cu șiruri este folosind tablourile unidimensionale, vectorii. Ne amintim că un vector este definit complet prin intermediul a trei caracteristici: tipul de date conținute, numele vectorului și numărul său de elemente. Așadar, putem declara un vector al cărui tip de data să fie char, caz în care acel vector va fi denumit șir (de caractere). &lt;br /&gt;
Declararea unui șir de caractere se face astfel: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
char numele_sirului [numarul_de_caractere];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt; &amp;#039;&amp;#039;&amp;#039; Observație: &amp;#039;&amp;#039;&amp;#039; Spre deosebire de vectorii studiați în laboratorul anterior, ale căror elemente sunt precizate explicit, șirurile au un caracter special, implicit, numit end of string și reprezentat astfel: \0.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operații cu șiruri == &lt;br /&gt;
  &lt;br /&gt;
Toate proprietățile vectorilor, studiate în laboratorul anterior, sunt valabile și în cazul șirurilor. De asemenea, toate operațiile pe care le putem face cu vectori sunt posibile și în cazul șirurilor. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt; &amp;#039;&amp;#039;&amp;#039; Observație: &amp;#039;&amp;#039;&amp;#039; Există  anumite operații asociate exclusiv șirurilor, precum căutarea unor caractere sau a unui șir într-un alt șir, concatenarea, etc. Toate aceste operații au funcții predefinite, care pot fi găsite într-un header specific, string.h. &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Aflarea lungimii unui șir de caractere === &lt;br /&gt;
Pe lângă metoda clasică, discutată în capitolul anterior, ce presupune parcurgerea șirului și numărarea elementelor acestuia, avem și o metodă proprie șirurilor. Ea presupune apelarea funcției strlen(), predefinita în biblioteca string.h, care va întoarce numărul de elemente al șirului. &lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt; &amp;#039;&amp;#039;&amp;#039; Observație: &amp;#039;&amp;#039;&amp;#039; Caracterul &amp;#039;\0&amp;#039; marchează sfârșitul șirului, iar acolo se oprește numărarea.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Sintaxa generala:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
lungime_sir = strlen (sir_de_caractere);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Citirea unui șir de caractere === &lt;br /&gt;
Există mai multe variante pentru a citi un șir de caractere, unele asemănătoare vectorilor, altele specifice șirurilor de caractere. &lt;br /&gt;
&lt;br /&gt;
1. Citirea șirului caracter cu caracter, până la întâlnirea caracterului cu codul ASCII 10 (newline - \n), moment în care se scrie caracterul de sfârșit de șir (null terminator - \0):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
char sir_de_caractere[MAX_SIZE];&lt;br /&gt;
int i;&lt;br /&gt;
for (i = 0; i &amp;lt; MAX_SIZE; i++) {&lt;br /&gt;
    scanf (&amp;quot;%c&amp;quot;, &amp;amp;sir_de_caractere[i]);&lt;br /&gt;
    /* 10 este codul ascii pentru \n, adica enter */&lt;br /&gt;
    if (sir_de_caractere[i] == 10) {&lt;br /&gt;
        sir_de_caractere[i] = &amp;#039;\0&amp;#039;;&lt;br /&gt;
        break;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Se folosește &amp;lt;code&amp;gt;scanf&amp;lt;/code&amp;gt; cu template-ul &amp;lt;code&amp;gt;%s&amp;lt;/code&amp;gt; (atenție, acest &amp;lt;code&amp;gt;scanf&amp;lt;/code&amp;gt; va citi exclusiv până la primul caracter alb - spațiu, tab sau newline):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
char sir_de_caractere[MAX_SIZE];&lt;br /&gt;
scanf (&amp;quot;%s&amp;quot;, sir_de_caractere);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3.  Se folosește &amp;lt;code&amp;gt;scanf&amp;lt;/code&amp;gt; cu template-ul &amp;lt;code&amp;gt;%[^\n]&amp;lt;/code&amp;gt; (atenție, acest &amp;lt;code&amp;gt;scanf&amp;lt;/code&amp;gt; va citi exclusiv până la primul newline pe care nu îl va consuma din stream - acesta va trebui eliminat manual cu apel de &amp;lt;code&amp;gt;getchar()&amp;lt;/code&amp;gt;):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
char sir_de_caractere[MAX_SIZE];&lt;br /&gt;
scanf (&amp;quot;%[^\n]&amp;quot;, sir_de_caractere);&lt;br /&gt;
getchar();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4. Se folosește &amp;lt;code&amp;gt;fgets&amp;lt;/code&amp;gt; (atenție, acestă funcție va citi maxim MAX_SIZE - 1 caractere de la tastatură, sau până la întâlnirea lui \n, în care situație caracterul \n va fi adăugat în șir):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
char sir_de_caractere[MAX_SIZE];&lt;br /&gt;
fgets(sir_de_caractere, MAX_SIZE, stdin);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Afișarea unui șir de caractere === &lt;br /&gt;
Analog citirii unui șir de caractere, afișarea se poate face și ea în mai multe moduri, după cum urmează:&lt;br /&gt;
  &lt;br /&gt;
1. Sintaxa generala:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
char sir_de_caractere[MAX_SIZE]; &lt;br /&gt;
scanf(&amp;quot;%s&amp;quot;,sir_de_caractere); // citire sir de caractere&lt;br /&gt;
&lt;br /&gt;
int i;&lt;br /&gt;
for (i = 0; i &amp;lt; MAX_SIZE &amp;amp;&amp;amp; sir_de_caractere [i] != &amp;#039;\0&amp;#039;; i++) {&lt;br /&gt;
    printf (&amp;quot;%c&amp;quot;, sir_de_caractere [i]);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Sintaxa generala&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
printf (&amp;quot;%s&amp;quot;, sir_de_caractere);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
3. Sintaxa generala:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
puts(sir_de_caractere);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Exemplu&amp;#039;&amp;#039;&amp;#039;: Fie șirul de caractere sir[10]. Citiți următoarea frază folosind toate cele 3 metode, apoi afișați conținutul șirului folosind puts();. Ce observați? Explicați.&lt;br /&gt;
&lt;br /&gt;
=== Căutarea unui caracter într-un șir de caractere === &lt;br /&gt;
Funcția folosită: strchr(); &lt;br /&gt;
Sintaxa generala:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
char sir_de_caractere[MAX_SIZE], char caracterul_cautat;&lt;br /&gt;
char * pointer;&lt;br /&gt;
pointer = strchr(sir_de_caractere, caracterul_cautat);&lt;br /&gt;
int pozitie = pointer - sir_de_caractere;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt; &amp;#039;&amp;#039;&amp;#039; Observație: &amp;#039;&amp;#039;&amp;#039; Funcția strchr NU oferă toate pozițiile pe care se află caracterul_căutat, ci doar prima poziție. &lt;br /&gt;
*Pentru a afla ultima poziție pe care se află un caracter căutat, se va folosi funcția strrchr(), sintaxa fiind identică. &lt;br /&gt;
*Pentru a caută un șir de caractere într-un alt șir de caractere, se va folosi funcția strstr(), sintaxa fiind aceeași. &lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Copierea unui șir de caractere  în altul === &lt;br /&gt;
Funcția folosită: strcpy (); &lt;br /&gt;
Sintaxa:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
char destinatie[MAX_SIZE1], sursa[MAX_SIZE2];&lt;br /&gt;
strcpy(destinatie, sursa);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt; &amp;#039;&amp;#039;&amp;#039; Observație: &amp;#039;&amp;#039;&amp;#039; șirul sursă se copiază în șirul destinație. Dacă lungimea șirului destinație este mai mică decât a șirului sursă, atunci copierea se face cu erori. Trebuie deci să punem următoarea condiție: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
MAX_SIZE1 &amp;gt;= strlen(sursa);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Concatenarea unor șiruri de caractere ===&lt;br /&gt;
Funcția folosită: srtcat();&lt;br /&gt;
Sintaxa generala:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
char destinatie[MAX_SIZE1], sursa[MAX_SIZE2];&lt;br /&gt;
strcat(destinatie, sursa); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt; &amp;#039;&amp;#039;&amp;#039; Observație: &amp;#039;&amp;#039;&amp;#039; Concatenarea se face adăugând șirul sursă la șirul destinație. Este deci necesar ca șirul sursă să &amp;quot;încăpă&amp;quot; în șirul destinație. Matematic, asta se traduce astfel: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
MAX_SIZE1 &amp;gt;= strlen(sursa) + strlen(destinatie); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Compararea  a doua șiruri de caractere ===&lt;br /&gt;
Funcția folosită: strcmp();&lt;br /&gt;
Sintaxa generala:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
char sir1 [MAX_SIZE1], sir2 [MAX_SIZE2];&lt;br /&gt;
int rezultat;&lt;br /&gt;
rezultat = strcmp(sir1, sir2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Funcția strcmp(); întoarce următoarele valori: &lt;br /&gt;
* un număr negativ - dacă sir1 este înainte din punct de vedere alfabetic; &lt;br /&gt;
* 0 - dacă cele două șiruri sunt identice; &lt;br /&gt;
* un număr pozitiv - dacă sir2 este înainte din punct de vedere alfabetic.&lt;br /&gt;
&lt;br /&gt;
=== Inserția unui șir de caractere într-un alt șir === &lt;br /&gt;
Pentru această operație nu există o funcție specializată în biblioteca string.h. Ceea ce vom face va fi să folosim procedee învățate la vectori, cât și funcții menționate anterior. Etapele sunt următoarele: &lt;br /&gt;
* declarăm cele două șiruri; &lt;br /&gt;
* verificăm dacă șirul ce urmează să fie introdus încape în șirul inițial; &lt;br /&gt;
* găsim poziția unde dorim să adăugăm șirul ce urmează să fie introdus; &lt;br /&gt;
* începând cu acea poziție, mutăm toate caracterele la dreaptă cu un număr de poziții egal cu lungimea șirului ce urmează să fie introdus; &lt;br /&gt;
* pe pozițiile rămase &amp;quot;goale&amp;quot; introducem șirul nou. &lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Exemplu:&amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
Transformați fraza &amp;quot;Studentul a picat examenul final.&amp;quot; în &amp;quot;Studentul nu a picat examenul final.&amp;quot; &lt;br /&gt;
Date necesare: sir_inițial[50] = &amp;quot;Sudentul a picat examenul final.&amp;quot;, sir_nou[3] = &amp;quot;nu &amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Observații și exemple==&lt;br /&gt;
&lt;br /&gt;
=== strlen vs sizeof ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
	char str1[20] = &amp;quot;StringLab&amp;quot;;&lt;br /&gt;
	int len,size;&lt;br /&gt;
&lt;br /&gt;
	len = strlen(str1);&lt;br /&gt;
	size = sizeof(str1); &lt;br /&gt;
	printf(&amp;quot;Lungimea str1: %d\n&amp;quot;, len);&lt;br /&gt;
	printf(&amp;quot;Lungimea total alocata str1: %d\n&amp;quot;, size);&lt;br /&gt;
&lt;br /&gt;
     return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== strchr vs strrchr ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
    	char str1[40] = &amp;quot;Cautare de caracter printre caractere&amp;quot;;&lt;br /&gt;
    	printf (&amp;quot;Caz1: %s\n&amp;quot;, strchr(str1, &amp;#039;a&amp;#039;));&lt;br /&gt;
    	printf (&amp;quot;Caz2: %s\n&amp;quot;, strrchr(str1, &amp;#039;a&amp;#039;));&lt;br /&gt;
        printf (&amp;quot;Caz3: %s\n&amp;quot;, strstr(str1, &amp;quot;de&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
     return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Exemple operații cu șiruri===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main () {&lt;br /&gt;
&lt;br /&gt;
   char str1[10] = &amp;quot;Hello&amp;quot;;&lt;br /&gt;
   char str2[10] = &amp;quot;String Lab&amp;quot;;&lt;br /&gt;
   char str3[10];&lt;br /&gt;
   int  len ;&lt;br /&gt;
&lt;br /&gt;
   /* copiaza str1 in str3 */&lt;br /&gt;
   strcpy(str3, str1);&lt;br /&gt;
   printf(&amp;quot;strcpy( str3, str1) :  %s\n&amp;quot;, str3 );&lt;br /&gt;
&lt;br /&gt;
   /* concateneaza str1 str2 */&lt;br /&gt;
   strcat( str1, str2);&lt;br /&gt;
   printf(&amp;quot;strcat( str1, str2):   %s\n&amp;quot;, str1 );&lt;br /&gt;
&lt;br /&gt;
   /* lungimea str1 dupa concatenare */&lt;br /&gt;
   len = strlen(str1);&lt;br /&gt;
   printf(&amp;quot;strlen(str1) :  %d\n&amp;quot;, len );&lt;br /&gt;
&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Model de concatenare fără a utiliza strcat ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(){&lt;br /&gt;
&lt;br /&gt;
   char str1[10], str2[10], str3[20];&lt;br /&gt;
   int i, poz;&lt;br /&gt;
   printf(&amp;quot;Introduceti sir1: &amp;quot;);&lt;br /&gt;
   scanf(&amp;quot;%s&amp;quot;,str1);&lt;br /&gt;
   printf(&amp;quot;Introduceti sir2: &amp;quot;);&lt;br /&gt;
   scanf(&amp;quot;%s&amp;quot;,str2);&lt;br /&gt;
&lt;br /&gt;
	for (i = 0; i &amp;lt; strlen(str1); i++)&lt;br /&gt;
		str3[i] = str1[i];&lt;br /&gt;
		poz=i;&lt;br /&gt;
	for (i = 0; i &amp;lt; strlen(str2); i++)&lt;br /&gt;
		str3[poz+i] = str2[i];&lt;br /&gt;
		str3[poz+i] =&amp;#039;\0&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Sir concatenat: %s\n&amp;quot;,str3); &lt;br /&gt;
&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Exemple fgets &amp;amp; puts ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
int main(){&lt;br /&gt;
    char nume[30];&lt;br /&gt;
    printf(&amp;quot;Numele este: &amp;quot;);&lt;br /&gt;
   /* Citește string de la utilizator */&lt;br /&gt;
    fgets(nume, 30, stdin);     &lt;br /&gt;
    printf(&amp;quot;Nume: &amp;quot;);&lt;br /&gt;
   /* Afișează string */&lt;br /&gt;
    puts(nume);    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Exerciții ==&lt;br /&gt;
&lt;br /&gt;
#Să se scrie un program care citește de la tastatură un cuvânt.Să se afișeze cuvintele ce se obțin prin eliminarea succesiva a primei si ultimei litere din cuvântul citit.&lt;br /&gt;
#Să se scrie un program care șterge toate caracterele dintr-o linie citită de la tastatură cu excepția literelor.&lt;br /&gt;
#Să se scrie un program care afișează pe ecran frecvența de apariție a unui caracter citit de la tastatură.&lt;br /&gt;
#Se citeşte de la tastatură o propoziţie (şir de caractere) terminată cu punct.Să se afişeze fiecare cuvânt din propoziţie pe câte o linie separată.&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=CID_aplicatii_9_:_Numaratorul&amp;diff=7388</id>
		<title>CID aplicatii 9 : Numaratorul</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=CID_aplicatii_9_:_Numaratorul&amp;diff=7388"/>
		<updated>2022-04-20T17:05:32Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Exemplul 1: Implementarea unui num[r[tor cu reset sincron */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Numărătorul ==&lt;br /&gt;
Numărătorul este cel mai simplu automat, fiind format dintr-un registru (element de memorare) ce reține valoarea curentă a acestuia și un circuit de incrementare (circuit de reacție) ce generează la ieșirea sa valoarea ce va trebui stocată în registru la următorul front crescător de ceas (valoarea curentă incrementată cu 1). &lt;br /&gt;
&lt;br /&gt;
În figura de mai jos este reprezentat un numărător cu reset sincron:&lt;br /&gt;
&lt;br /&gt;
[[Fișier:Numarator cu reset.png|600px]]&lt;br /&gt;
&lt;br /&gt;
În cazul de mai sus, cât timp semnalul &amp;#039;&amp;#039;reset&amp;#039;&amp;#039; este activ, valoarea numărătorului va fi 0. Atunci când semnalul &amp;#039;&amp;#039;reset&amp;#039;&amp;#039; nu este activ, numărătorul își va incrementa valoarea la fiecare front crescător de ceas.&lt;br /&gt;
&lt;br /&gt;
== Divizor de frecvență cu factor de divizare putere a lui 2==&lt;br /&gt;
În unele cazuri, apare necesitatea obținerii unor semnale de ceas cu frecvență mai mică decât cea a ceasului de sistem. Aceste noi semnale de ceas pot fi obținute chiar din semnalul de ceas al sistemului, prin circuite care realizează divizarea acestuia. Cea mai simplă divizare a unui semnal de ceas este cea cu factor de divizare egal cu o putere a lui 2. Pentru acest caz, putem folosi un numărător.&lt;br /&gt;
&lt;br /&gt;
Dacă urmărim figura de mai jos în care sunt reprezentate variațiile fiecărui bit în timpul funcționării unui numărător pe 4 biți, observăm că, cu cât ordinul bitului crește (este mai semnificativ), frecvența de variație este mai mică. Între frecvențele de variație corespunzătoare a doi biți succesivi există următoarea relație: frecvența unui bit este de două ori mai mică decât frecvența bitului anterior (mai puțin semnificativ).&lt;br /&gt;
&lt;br /&gt;
[[Fișier:Divizare frecventa.png]]&lt;br /&gt;
&lt;br /&gt;
Observând că frecvența bitului 0 este de două ori mai mică decât cea a ceasului, putem concluziona că frecvența de variație a bitului cu indicele N este dată de: &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;f&amp;lt;sub&amp;gt;bN&amp;lt;/sub&amp;gt;&amp;#039;&amp;#039; = &amp;#039;&amp;#039;f&amp;lt;sub&amp;gt;clk&amp;lt;/sub&amp;gt; / 2&amp;lt;sup&amp;gt;N+1&amp;lt;/sup&amp;gt;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Așadar, pentru a realiza un divizor de frecvență cu factor de divizare putere a lui 2, putem folosi un numărător îndeajuns de mare, din care extragem bitul cu frecvența de variație egală cu frecvența dorită.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exemple==&lt;br /&gt;
===Exemplul 1: Implementarea unui numărător cu reset sincron===&lt;br /&gt;
În acest exemplu vom realiza implementarea numărătorului cu reset sincron prezentat în figura din secțiunea de introducere teoretică. În plus, vom folosi parametrul WIDTH pentru a controla dimensiunea acestuia.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Implementarea Numărătorului cu reset sincron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Verilog&amp;quot;&amp;gt;&lt;br /&gt;
module Numarator&lt;br /&gt;
#(parameter WIDTH = 8)&lt;br /&gt;
(&lt;br /&gt;
    input clock,&lt;br /&gt;
    input reset,&lt;br /&gt;
    output reg [WIDTH-1:0] count  &lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
always@(posedge clock) begin&lt;br /&gt;
    if(reset == 0)&lt;br /&gt;
        count &amp;lt;= 0;&lt;br /&gt;
    else&lt;br /&gt;
        count &amp;lt;= count + 1;  &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
endmodule&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Implementarea unui modul de test pentru numărător&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Verilog&amp;quot;&amp;gt;&lt;br /&gt;
`timescale 1ns/1ps&lt;br /&gt;
&lt;br /&gt;
module Numarator_TB();&lt;br /&gt;
&lt;br /&gt;
parameter WIDTH_T = 5;&lt;br /&gt;
reg reset_t, clock_t;&lt;br /&gt;
wire [WIDTH_T-1:0] count_t;&lt;br /&gt;
	&lt;br /&gt;
initial begin&lt;br /&gt;
    clock_t = 0;&lt;br /&gt;
    forever #1 clock_t = ~clock_t;&lt;br /&gt;
end&lt;br /&gt;
	&lt;br /&gt;
initial begin&lt;br /&gt;
        reset_t = 0;&lt;br /&gt;
    #2 	reset_t = 1;&lt;br /&gt;
    #500 $stop();	&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
Numarator #(.WIDTH(WIDTH_T)) DUT(&lt;br /&gt;
    .clock(clock_t),&lt;br /&gt;
    .reset(reset_t),&lt;br /&gt;
    .count(count_t)&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
endmodule&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Observație:&amp;#039;&amp;#039;&amp;#039; Cât timp semnalul &amp;#039;&amp;#039;reset&amp;#039;&amp;#039; este inactiv, numărătorul își va incrementa valoarea la fiecare front crescător de ceas. Când va ajunge la valoarea sa maximă (de exemplu, 31 pentru un numărător pe 5 biți), va avea loc o depășire și având la dispozitie un număr limitat de biți (de exemplu, 5), semnalul de ieșire va deveni 0 (reținem doar cei mai puțin semnificativi 5 biți), circuitul reluând numărarea de la capat.&lt;br /&gt;
&lt;br /&gt;
===Exemplul 2: Observarea vitezei de variație a biților unui numărător===&lt;br /&gt;
În acest exemplu vom realiza implementarea unui divizor de frecvență ce generează la ieșire 4 semnale de ceas cu următoarele frecvențe:&lt;br /&gt;
* &amp;#039;&amp;#039;clkout1&amp;#039;&amp;#039;: semnal de ceas cu frecvența de 1 Hz.&lt;br /&gt;
* &amp;#039;&amp;#039;clkout2&amp;#039;&amp;#039;: semnal de ceas cu frecvența de 2 Hz.&lt;br /&gt;
* &amp;#039;&amp;#039;clkout4&amp;#039;&amp;#039;: semnal de ceas cu frecvența de 4 Hz.&lt;br /&gt;
* &amp;#039;&amp;#039;clkout8&amp;#039;&amp;#039;: semnal de ceas cu frecvența de 8 Hz.&lt;br /&gt;
&lt;br /&gt;
Dacă aplicăm formula &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;f&amp;lt;sub&amp;gt;bN&amp;lt;/sub&amp;gt;&amp;#039;&amp;#039; = &amp;#039;&amp;#039;f&amp;lt;sub&amp;gt;clk&amp;lt;/sub&amp;gt; / 2&amp;lt;sup&amp;gt;N+1&amp;lt;/sup&amp;gt;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; cunoscând că frecvența de ceas a FPGA-ului este de 125 MHz, vom obține:&lt;br /&gt;
* &amp;#039;&amp;#039;clkout1&amp;#039;&amp;#039; poate fi obținut prin bitul 26 al unui numărător.&lt;br /&gt;
* &amp;#039;&amp;#039;clkout2&amp;#039;&amp;#039; poate fi obținut prin bitul 25 al unui numărător.&lt;br /&gt;
* &amp;#039;&amp;#039;clkout4&amp;#039;&amp;#039; poate fi obținut prin bitul 24 al unui numărător.&lt;br /&gt;
* &amp;#039;&amp;#039;clkout8&amp;#039;&amp;#039; poate fi obținut prin bitul 23 al unui numărător.&lt;br /&gt;
&lt;br /&gt;
Din rezultatele de mai sus, rezultă că avem nevoie de un numărător pe 27 biți, astfel încât să putem folosi bitul cel mai semnificativ (bitul 26) pentru generarea semnalului de ceas cu frecvența cea mai mică.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Implementarea Verilog a circuitului&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Verilog&amp;quot;&amp;gt;&lt;br /&gt;
module clock_generator(&lt;br /&gt;
    input clock,&lt;br /&gt;
    input reset,&lt;br /&gt;
    output clkout1,&lt;br /&gt;
    output clkout2,&lt;br /&gt;
    output clkout4,&lt;br /&gt;
    output clkout8,&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
reg [26:0] count;&lt;br /&gt;
&lt;br /&gt;
always@(posedge clock) begin&lt;br /&gt;
    if(reset == 0)&lt;br /&gt;
        count &amp;lt;= 0;&lt;br /&gt;
    else&lt;br /&gt;
        count &amp;lt;= count + 1;  &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
assign clkout1 = count[26];&lt;br /&gt;
assign clkout2 = count[25];&lt;br /&gt;
assign clkout4 = count[24];&lt;br /&gt;
assign clkout8 = count[23];&lt;br /&gt;
&lt;br /&gt;
endmodule&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Implementarea circuitului pe FPGA&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Realizați sinteza circuitului pe FPGA, ținând cont de următoarele constrângeri de I/O:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-  align=&amp;quot;center&amp;quot;&lt;br /&gt;
||&amp;#039;&amp;#039;&amp;#039;Port&amp;#039;&amp;#039;&amp;#039; || &amp;#039;&amp;#039;&amp;#039;Conexiune&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
|-  align=&amp;quot;center&amp;quot;&lt;br /&gt;
| clock || CLK_125MHz&lt;br /&gt;
|-  align=&amp;quot;center&amp;quot;&lt;br /&gt;
| reset || Button 0 &lt;br /&gt;
|-  align=&amp;quot;center&amp;quot;&lt;br /&gt;
| clkout1 || LED3&lt;br /&gt;
|-  align=&amp;quot;center&amp;quot;&lt;br /&gt;
| clkout2  || LED2&lt;br /&gt;
|-  align=&amp;quot;center&amp;quot;&lt;br /&gt;
| clkout4  || LED1 &lt;br /&gt;
|-  align=&amp;quot;center&amp;quot;&lt;br /&gt;
| clkout8  || LED0 &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Observați viteza cu care fiecare din LED-uri se stinge și se aprinde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exerciții==&lt;br /&gt;
===Exercițiul 1===&lt;br /&gt;
Implementați un numărător parametrizat cu reset sincron și semnal de &amp;#039;&amp;#039;enable&amp;#039;&amp;#039;. Semnalul &amp;#039;&amp;#039;enable&amp;#039;&amp;#039; controlează funcționarea numărătorului astfel: când este activ (egal cu 1), permite funcționarea normală (incrementare la fiecare front crescător de ceas); când este inactiv (egal cu 0), va determina numărătorul să își păstreze valoarea curentă.&lt;br /&gt;
&lt;br /&gt;
Implementați și un modul de test care să testeze funcționarea corectă a circuitului.&lt;br /&gt;
&lt;br /&gt;
===Exercițiul 2===&lt;br /&gt;
Implementați un numărător parametrizat cu reset sincron și capacitatea de a număra crescător sau descrescător. Controlul direcției de numărare se va realiza cu ajutorul unui semnal &amp;#039;&amp;#039;count_updown&amp;#039;&amp;#039;, care controlează funcționarea numărătorului astfel: când este 0, numărătorul va număra crescător, prin incrementarea valorii curente, iar când este 1, numărătorul va număra descrescător, prin decrementarea valorii curente&lt;br /&gt;
&lt;br /&gt;
Implementați și un modul de test care să testeze funcționarea corectă a circuitului.&lt;br /&gt;
&lt;br /&gt;
===Exercițiul 3===&lt;br /&gt;
Implementați circuitul descris prin schema de mai jos, știind că:&lt;br /&gt;
* COUNTER este un numărător pe 32 biți fără reset.&lt;br /&gt;
* RAM este o memorie 16x4b, cu citire sincrona.&lt;br /&gt;
* ROM este o memorie 16x4b, ce are descrierea prezentată mai jos.&lt;br /&gt;
&lt;br /&gt;
[[Fișier:Cid_lab6.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Implementarea modulului ROM&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Verilog&amp;quot;&amp;gt;&lt;br /&gt;
module ROM(&lt;br /&gt;
    input [3:0] in,&lt;br /&gt;
    output reg [3:0] out&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
always @(in)&lt;br /&gt;
    case(in)&lt;br /&gt;
        0: out = 4&amp;#039;b0000;&lt;br /&gt;
        1: out = 4&amp;#039;b0110;&lt;br /&gt;
        2: out = 4&amp;#039;b0011;&lt;br /&gt;
        3: out = 4&amp;#039;b1110;&lt;br /&gt;
        4: out = 4&amp;#039;b1011;&lt;br /&gt;
        5: out = 4&amp;#039;b1111;&lt;br /&gt;
        6: out = 4&amp;#039;b0111;&lt;br /&gt;
        7: out = 4&amp;#039;b1100;&lt;br /&gt;
        8: out = 4&amp;#039;b0001;&lt;br /&gt;
        9: out = 4&amp;#039;b0101;&lt;br /&gt;
        10: out = 4&amp;#039;b1101;&lt;br /&gt;
        11: out = 4&amp;#039;b1010;&lt;br /&gt;
        12: out = 4&amp;#039;b0010;&lt;br /&gt;
        13: out = 4&amp;#039;b0100;&lt;br /&gt;
        14: out = 4&amp;#039;b1000;&lt;br /&gt;
        15: out = 4&amp;#039;b1001;&lt;br /&gt;
        default: out = 4&amp;#039;b0000;&lt;br /&gt;
    endcase&lt;br /&gt;
endmodule&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Realizați un modul de test în care să scrieți memoria RAM cu date, astfel încât să se realizeze citirea memoriei ROM în ordine, la fiecare ciclu de ceas (adresa 0 -&amp;gt; adresa 1 -&amp;gt; ... -&amp;gt; adresa 15 -&amp;gt; adresa 0 -&amp;gt; ...)&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7370</id>
		<title>C++ POO Lab Lucrarea 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7370"/>
		<updated>2022-04-12T22:01:59Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Exemplu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Această lucrare are ca scop familiarizarea cu următoarele noțiuni:&lt;br /&gt;
&lt;br /&gt;
* Moștenirea&lt;br /&gt;
* Ascunderea metodelor&lt;br /&gt;
* Polimorfismul&lt;br /&gt;
* Metode virtuale și suprascrierea metodelor&lt;br /&gt;
* Metode pur virtuale și clase abstracte&lt;br /&gt;
&lt;br /&gt;
= Moștenirea =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Moștenirea este mecanismul prin care o clasă preia structura (câmpurile) și comportamentul (metodele) unei alte (sau mai multor) clase, la care poate adăuga alți membri specifici.&lt;br /&gt;
&lt;br /&gt;
Clasa de la care se preiau membrii se numește:&lt;br /&gt;
* clasă de bază&lt;br /&gt;
* superclasă&lt;br /&gt;
&lt;br /&gt;
Clasa nouă, care preia membrii de la clasa de bază se numește:&lt;br /&gt;
* clasă derivată&lt;br /&gt;
* clasă extinsă&lt;br /&gt;
* subclasă&lt;br /&gt;
&lt;br /&gt;
În C++, moștenirea poate fi multiplă, în sensul că o clasă derivată poate moșteni mai multe clase de bază. Nu în toate limbajele există acest concept (în Java, de exemplu, există doar moștenire simplă - adică o clasă poate moșteni o singură altă clasă).&lt;br /&gt;
&lt;br /&gt;
Utilitatea moștenirii în programarea orientată pe obiecte este:&lt;br /&gt;
* reutilizarea codului existent fără modificarea acestuia;&lt;br /&gt;
* extinderea a unei clase deja scrise, fără a fi necesară recompilarea ei;&lt;br /&gt;
* utilizarea polimorfismului în timpul execuției, prin folosirea metodelor virtuale.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;29&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat() : mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Cat cat;&lt;br /&gt;
    cat.makeSound(); // makeSound este mostenita din clasa Animal&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În exemplul de mai sus, clasa &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; preia toți membrii din clasa &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; și adaugă un câmp &amp;lt;code&amp;gt;mLives&amp;lt;/code&amp;gt; și un constructor fără argumente. S-a introdus, de asemenea, un nou modificator de acces, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;, care permite accesul la membrul respectiv atât din clasa curentă cât și din orice clasă derivată din clasa curentă, dar nu și din alte clase sau funcții.&lt;br /&gt;
&lt;br /&gt;
Se observă, de asemenea, că moștenirea a fost declarată publică. Există două timpuri de moșteniri:&lt;br /&gt;
# publică&lt;br /&gt;
# privată&lt;br /&gt;
&lt;br /&gt;
Relativ la tipul de moștenire, mai jos este prezentat modul în care se preiau membrii din clasa de bază:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Accesul asupra membrilor moșteniți&lt;br /&gt;
|-&lt;br /&gt;
! Protecția in clasa de baza !! Modificatorul de acces utilizat în lista claselor de bază !! Dreptul de acces în clasa derivată&lt;br /&gt;
|-&lt;br /&gt;
| public || public || public&lt;br /&gt;
|-&lt;br /&gt;
| private || public || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || public || protected&lt;br /&gt;
|-&lt;br /&gt;
| public || private || private&lt;br /&gt;
|-&lt;br /&gt;
| private || private || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || private || private&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;A doua diferență între &amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;struct&amp;lt;/code&amp;gt; este că pentru prima, moștenirea implicită este &amp;#039;&amp;#039;&amp;#039;private&amp;#039;&amp;#039;&amp;#039; iar pentru a doua este &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Apelul constructorului superclasei ==&lt;br /&gt;
&lt;br /&gt;
Când se instanțiază o clasă derivată, constructorul acestei clase se ocupă de inițializarea câmpurilor definite în clasa derivată. Pentru a inițializa câmpurile din clasa de bază, este necesar să apelăm constructorul ei. Prin urmare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Obligatoriu, constructorul unei clase derivate trebuie să apeleze constructorul clasei de bază. Dacă acest apel nu se face explicit, compilatorul va introduce un apel către constructorul clasei de bază fără argumente. Dacă acesta lipsește, apelul către constructorul clasei de bază trebuie făcut explicit, altfel se va genera o eroare de compilare.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apelul constructorului superclasei se face folosind aceeași sintaxă ca pentru inițializarea câmpurilor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;32&amp;quot;&amp;gt;&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ascunderea metodelor =&lt;br /&gt;
&lt;br /&gt;
În anumite situații, există nevoia ca o anumită metodă care este moștenită din clasa de bază să se comporte altfel în clasa derivată. Putem realiza acest lucru reimplementând metoda respectivă, cu aceeași semnătură, în clasa derivată. Acest mecanism se numește ascundere (hiding):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;39-41&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    animal.makeSound();&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    cat.makeSound();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Polimorfismul =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Polimorfismul -- din greacă &amp;quot;poly&amp;quot; (mai multe) and &amp;quot;morphe&amp;quot; (forme) -- se referă la faptul că un obiect care este de tipul unei clase derivate, este în același timp și de tipul clasei de bază. Altfel spus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Dacă o clasă &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; extinde (direct sau indirect) o clasă &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;, atunci un obiect &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; de tipul &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; este în același timp și de tipul &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folosind acest concept, care este implementat și în limbajul C++, se pot utiliza pointeri sau referințe de un tip &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; pentru a referi obiecte de tipuri derivate din &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;50&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Animal Spot makes a sound!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Se vede că pe linia 50 de mai sus, avem o referință de tip &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; la un obiect de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;. Acest lucru este posibil pentru că o &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; este în același timp și un &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; (deoarece &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; extinde &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt;). Totuși, se poate observa din textul de ieșire că deși referințele &amp;lt;code&amp;gt;catRef&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;catRef2&amp;lt;/code&amp;gt; sunt către același obiect (de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;), apelul metodei &amp;lt;code&amp;gt;makeSound&amp;lt;/code&amp;gt; se face în funcție de tipul referinței, nu de tipul obiectului. Există însă scenarii în care se dorește comportamentul invers, anume apelul metodei în funcție de tipul obiectului, nu de tipul referinței cu care este accesat. Astfel, se introduce conceptul de &amp;#039;&amp;#039;&amp;#039;metodă virtuală&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
= Metode virtuale și suprascrierea metodelor =&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
Dacă o metodă este declarată virtuală, folosind cuvântul cheie &amp;lt;code&amp;gt;virtual&amp;lt;/code&amp;gt; plasat în fața tipului întors, atunci reimplementarea acesteia în clasele derivate se numește &amp;#039;&amp;#039;&amp;#039;suprascriere&amp;#039;&amp;#039;&amp;#039;. Apelul unei metode virtuale folosind o referință de alt tip decât al clasei din care face parte obiectul, va apela metoda corespunzătoare obiectului în sine, nu cea care aparține tipului referinței.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;15,39&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sfat&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;darkgreen&amp;quot;&amp;gt;Sfat:&amp;lt;/font&amp;gt; Când se suprascrie o metodă într-o clasă derivată, este recomandat să plasați înainte de acolada deschisă care implementează metoda cuvântul cheie &amp;lt;code&amp;gt;override&amp;lt;/code&amp;gt;. Deși acest lucru nu este obligatoriu, vă va avertiza printr-o eroare de compilare dacă suprascrierea nu se face corect (de exemplu dacă metoda din clasa de bază nu este declarată virtuală).&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Metode pur virtuale și clase abstracte =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
În anumite situații, o metodă virtuală nu poate avea o implementare în clasa de bază, pentru că nu este cunoscut modul în care aceasta se comportă. În această situație, metoda poate fi definită ca fiind &amp;#039;&amp;#039;&amp;#039;pur virtuală&amp;#039;&amp;#039;&amp;#039;, adică o metodă fără implementare, dar care este totuși declarată în cadrul clasei. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Dacă o clasă conține cel puțin o metodă pur virtuală aceasta se numește &amp;#039;&amp;#039;&amp;#039;clasă abstractă&amp;#039;&amp;#039;&amp;#039; și nu poate fi instanțiată.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dacă am crea un obiect de tipul respectiv, atunci nu am putea apela metoda pur virtuală pentru că implementarea aceasteia lipsește. Clasele abstracte se pot folosi numai pentru a fi extinse, și metodele pur virtuale trebuie suprascrise în clasele derivate. Dacă cel puțin una din metodele pur virtuale nu este suprascrisă, atunci clasa derivată este la rândul ei abstractă.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;24,45&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual int getNumberOfLegs() const = 0;&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int getNumberOfLegs() const override {&lt;br /&gt;
        return 4;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;); // eroare de compilare, Animal este clasa abstracta&lt;br /&gt;
    &lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7369</id>
		<title>C++ POO Lab Lucrarea 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7369"/>
		<updated>2022-04-12T22:01:25Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Exemplu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Această lucrare are ca scop familiarizarea cu următoarele noțiuni:&lt;br /&gt;
&lt;br /&gt;
* Moștenirea&lt;br /&gt;
* Ascunderea metodelor&lt;br /&gt;
* Polimorfismul&lt;br /&gt;
* Metode virtuale și suprascrierea metodelor&lt;br /&gt;
* Metode pur virtuale și clase abstracte&lt;br /&gt;
&lt;br /&gt;
= Moștenirea =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Moștenirea este mecanismul prin care o clasă preia structura (câmpurile) și comportamentul (metodele) unei alte (sau mai multor) clase, la care poate adăuga alți membri specifici.&lt;br /&gt;
&lt;br /&gt;
Clasa de la care se preiau membrii se numește:&lt;br /&gt;
* clasă de bază&lt;br /&gt;
* superclasă&lt;br /&gt;
&lt;br /&gt;
Clasa nouă, care preia membrii de la clasa de bază se numește:&lt;br /&gt;
* clasă derivată&lt;br /&gt;
* clasă extinsă&lt;br /&gt;
* subclasă&lt;br /&gt;
&lt;br /&gt;
În C++, moștenirea poate fi multiplă, în sensul că o clasă derivată poate moșteni mai multe clase de bază. Nu în toate limbajele există acest concept (în Java, de exemplu, există doar moștenire simplă - adică o clasă poate moșteni o singură altă clasă).&lt;br /&gt;
&lt;br /&gt;
Utilitatea moștenirii în programarea orientată pe obiecte este:&lt;br /&gt;
* reutilizarea codului existent fără modificarea acestuia;&lt;br /&gt;
* extinderea a unei clase deja scrise, fără a fi necesară recompilarea ei;&lt;br /&gt;
* utilizarea polimorfismului în timpul execuției, prin folosirea metodelor virtuale.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;29&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat() : mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Cat cat;&lt;br /&gt;
    cat.makeSound(); // makeSound este mostenita din clasa Animal&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În exemplul de mai sus, clasa &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; preia toți membrii din clasa &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; și adaugă un câmp &amp;lt;code&amp;gt;mLives&amp;lt;/code&amp;gt; și un constructor fără argumente. S-a introdus, de asemenea, un nou modificator de acces, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;, care permite accesul la membrul respectiv atât din clasa curentă cât și din orice clasă derivată din clasa curentă, dar nu și din alte clase sau funcții.&lt;br /&gt;
&lt;br /&gt;
Se observă, de asemenea, că moștenirea a fost declarată publică. Există două timpuri de moșteniri:&lt;br /&gt;
# publică&lt;br /&gt;
# privată&lt;br /&gt;
&lt;br /&gt;
Relativ la tipul de moștenire, mai jos este prezentat modul în care se preiau membrii din clasa de bază:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Accesul asupra membrilor moșteniți&lt;br /&gt;
|-&lt;br /&gt;
! Protecția in clasa de baza !! Modif de acces utilizat în lista claselor de bază !! Dreptul de acces în clasa derivată&lt;br /&gt;
|-&lt;br /&gt;
| public || public || public&lt;br /&gt;
|-&lt;br /&gt;
| private || public || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || public || protected&lt;br /&gt;
|-&lt;br /&gt;
| public || private || private&lt;br /&gt;
|-&lt;br /&gt;
| private || private || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || private || private&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;A doua diferență între &amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;struct&amp;lt;/code&amp;gt; este că pentru prima, moștenirea implicită este &amp;#039;&amp;#039;&amp;#039;private&amp;#039;&amp;#039;&amp;#039; iar pentru a doua este &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Apelul constructorului superclasei ==&lt;br /&gt;
&lt;br /&gt;
Când se instanțiază o clasă derivată, constructorul acestei clase se ocupă de inițializarea câmpurilor definite în clasa derivată. Pentru a inițializa câmpurile din clasa de bază, este necesar să apelăm constructorul ei. Prin urmare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Obligatoriu, constructorul unei clase derivate trebuie să apeleze constructorul clasei de bază. Dacă acest apel nu se face explicit, compilatorul va introduce un apel către constructorul clasei de bază fără argumente. Dacă acesta lipsește, apelul către constructorul clasei de bază trebuie făcut explicit, altfel se va genera o eroare de compilare.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apelul constructorului superclasei se face folosind aceeași sintaxă ca pentru inițializarea câmpurilor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;32&amp;quot;&amp;gt;&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ascunderea metodelor =&lt;br /&gt;
&lt;br /&gt;
În anumite situații, există nevoia ca o anumită metodă care este moștenită din clasa de bază să se comporte altfel în clasa derivată. Putem realiza acest lucru reimplementând metoda respectivă, cu aceeași semnătură, în clasa derivată. Acest mecanism se numește ascundere (hiding):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;39-41&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    animal.makeSound();&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    cat.makeSound();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Polimorfismul =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Polimorfismul -- din greacă &amp;quot;poly&amp;quot; (mai multe) and &amp;quot;morphe&amp;quot; (forme) -- se referă la faptul că un obiect care este de tipul unei clase derivate, este în același timp și de tipul clasei de bază. Altfel spus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Dacă o clasă &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; extinde (direct sau indirect) o clasă &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;, atunci un obiect &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; de tipul &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; este în același timp și de tipul &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folosind acest concept, care este implementat și în limbajul C++, se pot utiliza pointeri sau referințe de un tip &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; pentru a referi obiecte de tipuri derivate din &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;50&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Animal Spot makes a sound!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Se vede că pe linia 50 de mai sus, avem o referință de tip &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; la un obiect de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;. Acest lucru este posibil pentru că o &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; este în același timp și un &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; (deoarece &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; extinde &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt;). Totuși, se poate observa din textul de ieșire că deși referințele &amp;lt;code&amp;gt;catRef&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;catRef2&amp;lt;/code&amp;gt; sunt către același obiect (de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;), apelul metodei &amp;lt;code&amp;gt;makeSound&amp;lt;/code&amp;gt; se face în funcție de tipul referinței, nu de tipul obiectului. Există însă scenarii în care se dorește comportamentul invers, anume apelul metodei în funcție de tipul obiectului, nu de tipul referinței cu care este accesat. Astfel, se introduce conceptul de &amp;#039;&amp;#039;&amp;#039;metodă virtuală&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
= Metode virtuale și suprascrierea metodelor =&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
Dacă o metodă este declarată virtuală, folosind cuvântul cheie &amp;lt;code&amp;gt;virtual&amp;lt;/code&amp;gt; plasat în fața tipului întors, atunci reimplementarea acesteia în clasele derivate se numește &amp;#039;&amp;#039;&amp;#039;suprascriere&amp;#039;&amp;#039;&amp;#039;. Apelul unei metode virtuale folosind o referință de alt tip decât al clasei din care face parte obiectul, va apela metoda corespunzătoare obiectului în sine, nu cea care aparține tipului referinței.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;15,39&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sfat&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;darkgreen&amp;quot;&amp;gt;Sfat:&amp;lt;/font&amp;gt; Când se suprascrie o metodă într-o clasă derivată, este recomandat să plasați înainte de acolada deschisă care implementează metoda cuvântul cheie &amp;lt;code&amp;gt;override&amp;lt;/code&amp;gt;. Deși acest lucru nu este obligatoriu, vă va avertiza printr-o eroare de compilare dacă suprascrierea nu se face corect (de exemplu dacă metoda din clasa de bază nu este declarată virtuală).&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Metode pur virtuale și clase abstracte =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
În anumite situații, o metodă virtuală nu poate avea o implementare în clasa de bază, pentru că nu este cunoscut modul în care aceasta se comportă. În această situație, metoda poate fi definită ca fiind &amp;#039;&amp;#039;&amp;#039;pur virtuală&amp;#039;&amp;#039;&amp;#039;, adică o metodă fără implementare, dar care este totuși declarată în cadrul clasei. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Dacă o clasă conține cel puțin o metodă pur virtuală aceasta se numește &amp;#039;&amp;#039;&amp;#039;clasă abstractă&amp;#039;&amp;#039;&amp;#039; și nu poate fi instanțiată.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dacă am crea un obiect de tipul respectiv, atunci nu am putea apela metoda pur virtuală pentru că implementarea aceasteia lipsește. Clasele abstracte se pot folosi numai pentru a fi extinse, și metodele pur virtuale trebuie suprascrise în clasele derivate. Dacă cel puțin una din metodele pur virtuale nu este suprascrisă, atunci clasa derivată este la rândul ei abstractă.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;24,45&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual int getNumberOfLegs() const = 0;&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int getNumberOfLegs() const override {&lt;br /&gt;
        return 4;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;); // eroare de compilare, Animal este clasa abstracta&lt;br /&gt;
    &lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7368</id>
		<title>C++ POO Lab Lucrarea 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7368"/>
		<updated>2022-04-12T22:00:26Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Introducere */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Această lucrare are ca scop familiarizarea cu următoarele noțiuni:&lt;br /&gt;
&lt;br /&gt;
* Moștenirea&lt;br /&gt;
* Ascunderea metodelor&lt;br /&gt;
* Polimorfismul&lt;br /&gt;
* Metode virtuale și suprascrierea metodelor&lt;br /&gt;
* Metode pur virtuale și clase abstracte&lt;br /&gt;
&lt;br /&gt;
= Moștenirea =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Moștenirea este mecanismul prin care o clasă preia structura (câmpurile) și comportamentul (metodele) unei alte (sau mai multor) clase, la care poate adăuga alți membri specifici.&lt;br /&gt;
&lt;br /&gt;
Clasa de la care se preiau membrii se numește:&lt;br /&gt;
* clasă de bază&lt;br /&gt;
* superclasă&lt;br /&gt;
&lt;br /&gt;
Clasa nouă, care preia membrii de la clasa de bază se numește:&lt;br /&gt;
* clasă derivată&lt;br /&gt;
* clasă extinsă&lt;br /&gt;
* subclasă&lt;br /&gt;
&lt;br /&gt;
În C++, moștenirea poate fi multiplă, în sensul că o clasă derivată poate moșteni mai multe clase de bază. Nu în toate limbajele există acest concept (în Java, de exemplu, există doar moștenire simplă - adică o clasă poate moșteni o singură altă clasă).&lt;br /&gt;
&lt;br /&gt;
Utilitatea moștenirii în programarea orientată pe obiecte este:&lt;br /&gt;
* reutilizarea codului existent fără modificarea acestuia;&lt;br /&gt;
* extinderea a unei clase deja scrise, fără a fi necesară recompilarea ei;&lt;br /&gt;
* utilizarea polimorfismului în timpul execuției, prin folosirea metodelor virtuale.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat() : mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Cat cat;&lt;br /&gt;
    cat.makeSound(); // makeSound este mostenita din clasa Animal&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În exemplul de mai sus, clasa &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; preia toți membrii din clasa &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; și adaugă un câmp &amp;lt;code&amp;gt;mLives&amp;lt;/code&amp;gt; și un constructor fără argumente. S-a introdus, de asemenea, un nou modificator de acces, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;, care permite accesul la membrul respectiv atât din clasa curentă cât și din orice clasă derivată din clasa curentă, dar nu și din alte clase sau funcții.&lt;br /&gt;
&lt;br /&gt;
Se observă, de asemenea, că moștenirea a fost declarată publică. Există două timpuri de moșteniri:&lt;br /&gt;
# publică&lt;br /&gt;
# privată&lt;br /&gt;
&lt;br /&gt;
Relativ la tipul de moștenire, mai jos este prezentat modul în care se preiau membrii din clasa de bază:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Accesul asupra membrilor moșteniți&lt;br /&gt;
|-&lt;br /&gt;
! Protecția in clasa de baza !! Modif de acces utilizat în lista claselor de bază !! Dreptul de acces în clasa derivată&lt;br /&gt;
|-&lt;br /&gt;
| public || public || public&lt;br /&gt;
|-&lt;br /&gt;
| private || public || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || public || protected&lt;br /&gt;
|-&lt;br /&gt;
| public || private || private&lt;br /&gt;
|-&lt;br /&gt;
| private || private || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || private || private&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;A doua diferență între &amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;struct&amp;lt;/code&amp;gt; este că pentru prima, moștenirea implicită este &amp;#039;&amp;#039;&amp;#039;private&amp;#039;&amp;#039;&amp;#039; iar pentru a doua este &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Apelul constructorului superclasei ==&lt;br /&gt;
&lt;br /&gt;
Când se instanțiază o clasă derivată, constructorul acestei clase se ocupă de inițializarea câmpurilor definite în clasa derivată. Pentru a inițializa câmpurile din clasa de bază, este necesar să apelăm constructorul ei. Prin urmare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Obligatoriu, constructorul unei clase derivate trebuie să apeleze constructorul clasei de bază. Dacă acest apel nu se face explicit, compilatorul va introduce un apel către constructorul clasei de bază fără argumente. Dacă acesta lipsește, apelul către constructorul clasei de bază trebuie făcut explicit, altfel se va genera o eroare de compilare.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apelul constructorului superclasei se face folosind aceeași sintaxă ca pentru inițializarea câmpurilor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;32&amp;quot;&amp;gt;&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ascunderea metodelor =&lt;br /&gt;
&lt;br /&gt;
În anumite situații, există nevoia ca o anumită metodă care este moștenită din clasa de bază să se comporte altfel în clasa derivată. Putem realiza acest lucru reimplementând metoda respectivă, cu aceeași semnătură, în clasa derivată. Acest mecanism se numește ascundere (hiding):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;39-41&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    animal.makeSound();&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    cat.makeSound();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Polimorfismul =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Polimorfismul -- din greacă &amp;quot;poly&amp;quot; (mai multe) and &amp;quot;morphe&amp;quot; (forme) -- se referă la faptul că un obiect care este de tipul unei clase derivate, este în același timp și de tipul clasei de bază. Altfel spus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Dacă o clasă &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; extinde (direct sau indirect) o clasă &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;, atunci un obiect &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; de tipul &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; este în același timp și de tipul &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folosind acest concept, care este implementat și în limbajul C++, se pot utiliza pointeri sau referințe de un tip &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; pentru a referi obiecte de tipuri derivate din &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;50&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Animal Spot makes a sound!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Se vede că pe linia 50 de mai sus, avem o referință de tip &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; la un obiect de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;. Acest lucru este posibil pentru că o &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; este în același timp și un &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; (deoarece &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; extinde &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt;). Totuși, se poate observa din textul de ieșire că deși referințele &amp;lt;code&amp;gt;catRef&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;catRef2&amp;lt;/code&amp;gt; sunt către același obiect (de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;), apelul metodei &amp;lt;code&amp;gt;makeSound&amp;lt;/code&amp;gt; se face în funcție de tipul referinței, nu de tipul obiectului. Există însă scenarii în care se dorește comportamentul invers, anume apelul metodei în funcție de tipul obiectului, nu de tipul referinței cu care este accesat. Astfel, se introduce conceptul de &amp;#039;&amp;#039;&amp;#039;metodă virtuală&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
= Metode virtuale și suprascrierea metodelor =&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
Dacă o metodă este declarată virtuală, folosind cuvântul cheie &amp;lt;code&amp;gt;virtual&amp;lt;/code&amp;gt; plasat în fața tipului întors, atunci reimplementarea acesteia în clasele derivate se numește &amp;#039;&amp;#039;&amp;#039;suprascriere&amp;#039;&amp;#039;&amp;#039;. Apelul unei metode virtuale folosind o referință de alt tip decât al clasei din care face parte obiectul, va apela metoda corespunzătoare obiectului în sine, nu cea care aparține tipului referinței.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;15,39&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sfat&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;darkgreen&amp;quot;&amp;gt;Sfat:&amp;lt;/font&amp;gt; Când se suprascrie o metodă într-o clasă derivată, este recomandat să plasați înainte de acolada deschisă care implementează metoda cuvântul cheie &amp;lt;code&amp;gt;override&amp;lt;/code&amp;gt;. Deși acest lucru nu este obligatoriu, vă va avertiza printr-o eroare de compilare dacă suprascrierea nu se face corect (de exemplu dacă metoda din clasa de bază nu este declarată virtuală).&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Metode pur virtuale și clase abstracte =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
În anumite situații, o metodă virtuală nu poate avea o implementare în clasa de bază, pentru că nu este cunoscut modul în care aceasta se comportă. În această situație, metoda poate fi definită ca fiind &amp;#039;&amp;#039;&amp;#039;pur virtuală&amp;#039;&amp;#039;&amp;#039;, adică o metodă fără implementare, dar care este totuși declarată în cadrul clasei. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Dacă o clasă conține cel puțin o metodă pur virtuală aceasta se numește &amp;#039;&amp;#039;&amp;#039;clasă abstractă&amp;#039;&amp;#039;&amp;#039; și nu poate fi instanțiată.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dacă am crea un obiect de tipul respectiv, atunci nu am putea apela metoda pur virtuală pentru că implementarea aceasteia lipsește. Clasele abstracte se pot folosi numai pentru a fi extinse, și metodele pur virtuale trebuie suprascrise în clasele derivate. Dacă cel puțin una din metodele pur virtuale nu este suprascrisă, atunci clasa derivată este la rândul ei abstractă.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;24,45&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual int getNumberOfLegs() const = 0;&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int getNumberOfLegs() const override {&lt;br /&gt;
        return 4;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;); // eroare de compilare, Animal este clasa abstracta&lt;br /&gt;
    &lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7367</id>
		<title>C++ POO Lab Lucrarea 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7367"/>
		<updated>2022-04-12T21:58:06Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Introducere */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Această lucrare are ca scop familiarizarea cu următoarele noțiuni:&lt;br /&gt;
&lt;br /&gt;
* Moștenirea&lt;br /&gt;
* Ascunderea metodelor&lt;br /&gt;
* Polimorfismul&lt;br /&gt;
* Metode virtuale și suprascrierea metodelor&lt;br /&gt;
* Metode pur virtuale și clase abstracte&lt;br /&gt;
&lt;br /&gt;
= Moștenirea =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Moștenirea este mecanismul prin care o clasă preia structura (câmpurile) și comportamentul (metodele) unei alte (sau mai multor) clase, la care poate adăuga alți membri specifici.&lt;br /&gt;
&lt;br /&gt;
Clasa de la care se preiau membrii se numește:&lt;br /&gt;
* clasă de bază&lt;br /&gt;
* superclasă&lt;br /&gt;
&lt;br /&gt;
Clasa nouă, care preia membrii de la clasa de bază se numește:&lt;br /&gt;
* clasă derivată&lt;br /&gt;
* clasă extinsă&lt;br /&gt;
* subclasă&lt;br /&gt;
&lt;br /&gt;
În C++, moștenirea poate fi multiplă, în sensul ca o clasa derivată poate moșteni mai multe clase de bază. Nu în toate limbajele există acest concept (în Java. de exemplu, există doar moștenire simplă - adică o clasă poate moșteni o singură altă clasă).&lt;br /&gt;
&lt;br /&gt;
Utilitatea moștenirii în programarea orientată pe obiecte este:&lt;br /&gt;
* reutilizarea codului existent fără modificarea acestuia;&lt;br /&gt;
* extinderea a unei clase deja scrise, fără a fi necesara recompilarea ei;&lt;br /&gt;
* utilizarea polimorfismului în timpul execuției, prin folosirea metodelor virtuale.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat() : mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Cat cat;&lt;br /&gt;
    cat.makeSound(); // makeSound este mostenita din clasa Animal&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În exemplul de mai sus, clasa &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; preia toți membrii din clasa &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; și adaugă un câmp &amp;lt;code&amp;gt;mLives&amp;lt;/code&amp;gt; și un constructor fără argumente. S-a introdus, de asemenea, un nou modificator de acces, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;, care permite accesul la membrul respectiv atât din clasa curentă cât și din orice clasă derivată din clasa curentă, dar nu și din alte clase sau funcții.&lt;br /&gt;
&lt;br /&gt;
Se observă, de asemenea, că moștenirea a fost declarată publică. Există două timpuri de moșteniri:&lt;br /&gt;
# publică&lt;br /&gt;
# privată&lt;br /&gt;
&lt;br /&gt;
Relativ la tipul de moștenire, mai jos este prezentat modul în care se preiau membrii din clasa de bază:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Accesul asupra membrilor moșteniți&lt;br /&gt;
|-&lt;br /&gt;
! Protecția in clasa de baza !! Modif de acces utilizat în lista claselor de bază !! Dreptul de acces în clasa derivată&lt;br /&gt;
|-&lt;br /&gt;
| public || public || public&lt;br /&gt;
|-&lt;br /&gt;
| private || public || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || public || protected&lt;br /&gt;
|-&lt;br /&gt;
| public || private || private&lt;br /&gt;
|-&lt;br /&gt;
| private || private || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || private || private&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;A doua diferență între &amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;struct&amp;lt;/code&amp;gt; este că pentru prima, moștenirea implicită este &amp;#039;&amp;#039;&amp;#039;private&amp;#039;&amp;#039;&amp;#039; iar pentru a doua este &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Apelul constructorului superclasei ==&lt;br /&gt;
&lt;br /&gt;
Când se instanțiază o clasă derivată, constructorul acestei clase se ocupă de inițializarea câmpurilor definite în clasa derivată. Pentru a inițializa câmpurile din clasa de bază, este necesar să apelăm constructorul ei. Prin urmare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Obligatoriu, constructorul unei clase derivate trebuie să apeleze constructorul clasei de bază. Dacă acest apel nu se face explicit, compilatorul va introduce un apel către constructorul clasei de bază fără argumente. Dacă acesta lipsește, apelul către constructorul clasei de bază trebuie făcut explicit, altfel se va genera o eroare de compilare.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apelul constructorului superclasei se face folosind aceeași sintaxă ca pentru inițializarea câmpurilor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;32&amp;quot;&amp;gt;&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ascunderea metodelor =&lt;br /&gt;
&lt;br /&gt;
În anumite situații, există nevoia ca o anumită metodă care este moștenită din clasa de bază să se comporte altfel în clasa derivată. Putem realiza acest lucru reimplementând metoda respectivă, cu aceeași semnătură, în clasa derivată. Acest mecanism se numește ascundere (hiding):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;39-41&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    animal.makeSound();&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    cat.makeSound();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Polimorfismul =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Polimorfismul -- din greacă &amp;quot;poly&amp;quot; (mai multe) and &amp;quot;morphe&amp;quot; (forme) -- se referă la faptul că un obiect care este de tipul unei clase derivate, este în același timp și de tipul clasei de bază. Altfel spus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Dacă o clasă &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; extinde (direct sau indirect) o clasă &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;, atunci un obiect &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; de tipul &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; este în același timp și de tipul &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folosind acest concept, care este implementat și în limbajul C++, se pot utiliza pointeri sau referințe de un tip &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; pentru a referi obiecte de tipuri derivate din &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;50&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Animal Spot makes a sound!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Se vede că pe linia 50 de mai sus, avem o referință de tip &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; la un obiect de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;. Acest lucru este posibil pentru că o &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; este în același timp și un &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; (deoarece &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; extinde &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt;). Totuși, se poate observa din textul de ieșire că deși referințele &amp;lt;code&amp;gt;catRef&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;catRef2&amp;lt;/code&amp;gt; sunt către același obiect (de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;), apelul metodei &amp;lt;code&amp;gt;makeSound&amp;lt;/code&amp;gt; se face în funcție de tipul referinței, nu de tipul obiectului. Există însă scenarii în care se dorește comportamentul invers, anume apelul metodei în funcție de tipul obiectului, nu de tipul referinței cu care este accesat. Astfel, se introduce conceptul de &amp;#039;&amp;#039;&amp;#039;metodă virtuală&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
= Metode virtuale și suprascrierea metodelor =&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
Dacă o metodă este declarată virtuală, folosind cuvântul cheie &amp;lt;code&amp;gt;virtual&amp;lt;/code&amp;gt; plasat în fața tipului întors, atunci reimplementarea acesteia în clasele derivate se numește &amp;#039;&amp;#039;&amp;#039;suprascriere&amp;#039;&amp;#039;&amp;#039;. Apelul unei metode virtuale folosind o referință de alt tip decât al clasei din care face parte obiectul, va apela metoda corespunzătoare obiectului în sine, nu cea care aparține tipului referinței.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;15,39&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sfat&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;darkgreen&amp;quot;&amp;gt;Sfat:&amp;lt;/font&amp;gt; Când se suprascrie o metodă într-o clasă derivată, este recomandat să plasați înainte de acolada deschisă care implementează metoda cuvântul cheie &amp;lt;code&amp;gt;override&amp;lt;/code&amp;gt;. Deși acest lucru nu este obligatoriu, vă va avertiza printr-o eroare de compilare dacă suprascrierea nu se face corect (de exemplu dacă metoda din clasa de bază nu este declarată virtuală).&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Metode pur virtuale și clase abstracte =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
În anumite situații, o metodă virtuală nu poate avea o implementare în clasa de bază, pentru că nu este cunoscut modul în care aceasta se comportă. În această situație, metoda poate fi definită ca fiind &amp;#039;&amp;#039;&amp;#039;pur virtuală&amp;#039;&amp;#039;&amp;#039;, adică o metodă fără implementare, dar care este totuși declarată în cadrul clasei. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Dacă o clasă conține cel puțin o metodă pur virtuală aceasta se numește &amp;#039;&amp;#039;&amp;#039;clasă abstractă&amp;#039;&amp;#039;&amp;#039; și nu poate fi instanțiată.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dacă am crea un obiect de tipul respectiv, atunci nu am putea apela metoda pur virtuală pentru că implementarea aceasteia lipsește. Clasele abstracte se pot folosi numai pentru a fi extinse, și metodele pur virtuale trebuie suprascrise în clasele derivate. Dacă cel puțin una din metodele pur virtuale nu este suprascrisă, atunci clasa derivată este la rândul ei abstractă.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;24,45&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual int getNumberOfLegs() const = 0;&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int getNumberOfLegs() const override {&lt;br /&gt;
        return 4;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;); // eroare de compilare, Animal este clasa abstracta&lt;br /&gt;
    &lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7366</id>
		<title>C++ POO Lab Lucrarea 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7366"/>
		<updated>2022-04-12T21:57:08Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Exemplu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Această lucrare are ca scop familiarizarea cu următoarele noțiuni:&lt;br /&gt;
&lt;br /&gt;
* Moștenirea&lt;br /&gt;
* Ascunderea metodelor&lt;br /&gt;
* Polimorfismul&lt;br /&gt;
* Metode virtuale și suprascrierea metodelor&lt;br /&gt;
* Metode pur virtuale și clase abstracte&lt;br /&gt;
&lt;br /&gt;
= Moștenirea =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Moștenirea este mecanismul prin care o clasă preia structura (câmpurile) și comportamentul (metodele) unei alte (sau mai multor) clase, la care poate adăuga alți membri specifici.&lt;br /&gt;
&lt;br /&gt;
Clasa de la care se preiau membrii se numește:&lt;br /&gt;
* clasă de bază&lt;br /&gt;
* superclasă&lt;br /&gt;
&lt;br /&gt;
Clasa nouă, care preia membrii de la clasa de bază se numește:&lt;br /&gt;
* clasă derivată&lt;br /&gt;
* clasă extinsă&lt;br /&gt;
* subclasă&lt;br /&gt;
&lt;br /&gt;
În C++, moștenirea poate fi multiplă, în sensul ca o clasa derivată poate moșteni mai multe clase de bază. Nu în toate limbajele există acest concept (în Java. de exemplu, există doar moștenire simplă - adică o clasă poate moșteni o singură altă clasă).&lt;br /&gt;
&lt;br /&gt;
Utilitatea moștenirii în programarea orientată pe obiecte este:&lt;br /&gt;
* reutilizarea codului existent fără modificarea acestuia;&lt;br /&gt;
* extinderea a unei clase deja scrise, fără a fi necesara recompilarea ei;&lt;br /&gt;
* utilizarea polimorfismului în timpul execuției, prin folosirea metodelor virtuale.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat() : mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Cat cat;&lt;br /&gt;
    cat.makeSound(); // makeSound este mostenita din clasa Animal&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În exemplul de mai sus, clasa &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; preia toți membrii din clasa &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; și adaugă un câmp &amp;lt;code&amp;gt;mLives&amp;lt;/code&amp;gt; și un constructor fără argumente. S-a introdus, de asemenea, un nou modificator de acces, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;, care permite accesul la membrul respectiv atât din clasa curentă cât și din orice clasă derivată din clasa curentă, dar nu și din alte clase sau funcții.&lt;br /&gt;
&lt;br /&gt;
Se observă, de asemenea, că moștenirea a fost declarată publică. Există două timpuri de moșteniri:&lt;br /&gt;
# publică&lt;br /&gt;
# privată&lt;br /&gt;
&lt;br /&gt;
Relativ la tipul de moștenire, mai jos este prezentat modul în care se preiau membrii din clasa de bază:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Accesul asupra membrilor moșteniți&lt;br /&gt;
|-&lt;br /&gt;
! Protecția in clasa de baza !! Modif de acces utilizat în lista claselor de bază !! Dreptul de acces în clasa derivată&lt;br /&gt;
|-&lt;br /&gt;
| public || public || public&lt;br /&gt;
|-&lt;br /&gt;
| private || public || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || public || protected&lt;br /&gt;
|-&lt;br /&gt;
| public || private || private&lt;br /&gt;
|-&lt;br /&gt;
| private || private || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || private || private&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;A doua diferență între &amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;struct&amp;lt;/code&amp;gt; este că pentru prima, moștenirea implicită este &amp;#039;&amp;#039;&amp;#039;private&amp;#039;&amp;#039;&amp;#039; iar pentru a doua este &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Apelul constructorului superclasei ==&lt;br /&gt;
&lt;br /&gt;
Când se instanțiază o clasă derivată, constructorul acestei clase se ocupă de inițializarea câmpurilor definite în clasa derivată. Pentru a inițializa câmpurile din clasa de bază, este necesar să apelăm constructorul ei. Prin urmare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Obligatoriu, constructorul unei clase derivate trebuie să apeleze constructorul clasei de bază. Dacă acest apel nu se face explicit, compilatorul va introduce un apel către constructorul clasei de bază fără argumente. Dacă acesta lipsește, apelul către constructorul clasei de bază trebuie făcut explicit, altfel se va genera o eroare de compilare.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apelul constructorului superclasei se face folosind aceeași sintaxă ca pentru inițializarea câmpurilor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;32&amp;quot;&amp;gt;&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ascunderea metodelor =&lt;br /&gt;
&lt;br /&gt;
În anumite situații, există nevoia ca o anumită metodă care este moștenită din clasa de bază să se comporte altfel în clasa derivată. Putem realiza acest lucru reimplementând metoda respectivă, cu aceeași semnătură, în clasa derivată. Acest mecanism se numește ascundere (hiding):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;39-41&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    animal.makeSound();&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    cat.makeSound();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Polimorfismul =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Polimorfismul -- din greacă &amp;quot;poly&amp;quot; (mai multe) and &amp;quot;morphe&amp;quot; (forme) -- se referă la faptul că un obiect care este de tipul unei clase derivate, este în același timp și de tipul clasei de bază. Altfel spus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Dacă o clasă &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; extinde (direct sau indirect) o clasă &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;, atunci un obiect &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; de tipul &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; este în același timp și de tipul &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folosind acest concept, care este implementat și în limbajul C++, se pot utiliza pointeri sau referințe de un tip &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; pentru a referi obiecte de tipuri derivate din &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;50&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Animal Spot makes a sound!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Se vede că pe linia 50 de mai sus, avem o referință de tip &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; la un obiect de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;. Acest lucru este posibil pentru că o &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; este în același timp și un &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; (deoarece &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; extinde &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt;). Totuși, se poate observa din textul de ieșire că deși referințele &amp;lt;code&amp;gt;catRef&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;catRef2&amp;lt;/code&amp;gt; sunt către același obiect (de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;), apelul metodei &amp;lt;code&amp;gt;makeSound&amp;lt;/code&amp;gt; se face în funcție de tipul referinței, nu de tipul obiectului. Există însă scenarii în care se dorește comportamentul invers, anume apelul metodei în funcție de tipul obiectului, nu de tipul referinței cu care este accesat. Astfel, se introduce conceptul de &amp;#039;&amp;#039;&amp;#039;metodă virtuală&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
= Metode virtuale și suprascrierea metodelor =&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
Dacă o metodă este declarată virtuală, folosind cuvântul cheie &amp;lt;code&amp;gt;virtual&amp;lt;/code&amp;gt; plasat în fața tipului întors, atunci reimplementarea acesteia în clasele derivate se numește &amp;#039;&amp;#039;&amp;#039;suprascriere&amp;#039;&amp;#039;&amp;#039;. Apelul unei metode virtuale folosind o referință de alt tip decât al clasei din care face parte obiectul, va apela metoda corespunzătoare obiectului în sine, nu cea care aparține tipului referinței.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;15,39&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sfat&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;darkgreen&amp;quot;&amp;gt;Sfat:&amp;lt;/font&amp;gt; Când se suprascrie o metodă într-o clasă derivată, este recomandat să plasați înainte de acolada deschisă care implementează metoda cuvântul cheie &amp;lt;code&amp;gt;override&amp;lt;/code&amp;gt;. Deși acest lucru nu este obligatoriu, vă va avertiza printr-o eroare de compilare dacă suprascrierea nu se face corect (de exemplu dacă metoda din clasa de bază nu este declarată virtuală).&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Metode pur virtuale și clase abstracte =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
În anumite situații, o metodă virtuală nu poate avea o implementare în clasa de bază, pentru că nu este cunoscut modul în care aceasta se comportă. În această situație, metoda poate fi definită ca fiind &amp;#039;&amp;#039;&amp;#039;pur virtuală&amp;#039;&amp;#039;&amp;#039;, adică o metodă fără implementare, dar care este totuși declarată în cadrul clasei. Dacă o clasă conține cel puțin o metodă pur virtuală aceasta se numește &amp;#039;&amp;#039;&amp;#039;clasă abstractă&amp;#039;&amp;#039;&amp;#039; și nu poate fi instanțiată. Dacă am crea un obiect de tipul respectiv, atunci nu am putea apela metoda pur virtuală pentru că implementarea aceasteia lipsește. Clasele abstracte se pot folosi numai pentru a fi extinse, și metodele pur virtuale trebuie suprascrise în clasele derivate. Dacă cel puțin una din metodele pur virtuale nu este suprascrisă, atunci clasa derivată este la rândul ei abstractă.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;24,45&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual int getNumberOfLegs() const = 0;&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int getNumberOfLegs() const override {&lt;br /&gt;
        return 4;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;); // eroare de compilare, Animal este clasa abstracta&lt;br /&gt;
    &lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7365</id>
		<title>C++ POO Lab Lucrarea 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7365"/>
		<updated>2022-04-12T21:56:23Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Exemplu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Această lucrare are ca scop familiarizarea cu următoarele noțiuni:&lt;br /&gt;
&lt;br /&gt;
* Moștenirea&lt;br /&gt;
* Ascunderea metodelor&lt;br /&gt;
* Polimorfismul&lt;br /&gt;
* Metode virtuale și suprascrierea metodelor&lt;br /&gt;
* Metode pur virtuale și clase abstracte&lt;br /&gt;
&lt;br /&gt;
= Moștenirea =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Moștenirea este mecanismul prin care o clasă preia structura (câmpurile) și comportamentul (metodele) unei alte (sau mai multor) clase, la care poate adăuga alți membri specifici.&lt;br /&gt;
&lt;br /&gt;
Clasa de la care se preiau membrii se numește:&lt;br /&gt;
* clasă de bază&lt;br /&gt;
* superclasă&lt;br /&gt;
&lt;br /&gt;
Clasa nouă, care preia membrii de la clasa de bază se numește:&lt;br /&gt;
* clasă derivată&lt;br /&gt;
* clasă extinsă&lt;br /&gt;
* subclasă&lt;br /&gt;
&lt;br /&gt;
În C++, moștenirea poate fi multiplă, în sensul ca o clasa derivată poate moșteni mai multe clase de bază. Nu în toate limbajele există acest concept (în Java. de exemplu, există doar moștenire simplă - adică o clasă poate moșteni o singură altă clasă).&lt;br /&gt;
&lt;br /&gt;
Utilitatea moștenirii în programarea orientată pe obiecte este:&lt;br /&gt;
* reutilizarea codului existent fără modificarea acestuia;&lt;br /&gt;
* extinderea a unei clase deja scrise, fără a fi necesara recompilarea ei;&lt;br /&gt;
* utilizarea polimorfismului în timpul execuției, prin folosirea metodelor virtuale.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat() : mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Cat cat;&lt;br /&gt;
    cat.makeSound(); // makeSound este mostenita din clasa Animal&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În exemplul de mai sus, clasa &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; preia toți membrii din clasa &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; și adaugă un câmp &amp;lt;code&amp;gt;mLives&amp;lt;/code&amp;gt; și un constructor fără argumente. S-a introdus, de asemenea, un nou modificator de acces, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;, care permite accesul la membrul respectiv atât din clasa curentă cât și din orice clasă derivată din clasa curentă, dar nu și din alte clase sau funcții.&lt;br /&gt;
&lt;br /&gt;
Se observă, de asemenea, că moștenirea a fost declarată publică. Există două timpuri de moșteniri:&lt;br /&gt;
# publică&lt;br /&gt;
# privată&lt;br /&gt;
&lt;br /&gt;
Relativ la tipul de moștenire, mai jos este prezentat modul în care se preiau membrii din clasa de bază:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Accesul asupra membrilor moșteniți&lt;br /&gt;
|-&lt;br /&gt;
! Protecția in clasa de baza !! Modif de acces utilizat în lista claselor de bază !! Dreptul de acces în clasa derivată&lt;br /&gt;
|-&lt;br /&gt;
| public || public || public&lt;br /&gt;
|-&lt;br /&gt;
| private || public || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || public || protected&lt;br /&gt;
|-&lt;br /&gt;
| public || private || private&lt;br /&gt;
|-&lt;br /&gt;
| private || private || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || private || private&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;A doua diferență între &amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;struct&amp;lt;/code&amp;gt; este că pentru prima, moștenirea implicită este &amp;#039;&amp;#039;&amp;#039;private&amp;#039;&amp;#039;&amp;#039; iar pentru a doua este &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Apelul constructorului superclasei ==&lt;br /&gt;
&lt;br /&gt;
Când se instanțiază o clasă derivată, constructorul acestei clase se ocupă de inițializarea câmpurilor definite în clasa derivată. Pentru a inițializa câmpurile din clasa de bază, este necesar să apelăm constructorul ei. Prin urmare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Obligatoriu, constructorul unei clase derivate trebuie să apeleze constructorul clasei de bază. Dacă acest apel nu se face explicit, compilatorul va introduce un apel către constructorul clasei de bază fără argumente. Dacă acesta lipsește, apelul către constructorul clasei de bază trebuie făcut explicit, altfel se va genera o eroare de compilare.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apelul constructorului superclasei se face folosind aceeași sintaxă ca pentru inițializarea câmpurilor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;32&amp;quot;&amp;gt;&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ascunderea metodelor =&lt;br /&gt;
&lt;br /&gt;
În anumite situații, există nevoia ca o anumită metodă care este moștenită din clasa de bază să se comporte altfel în clasa derivată. Putem realiza acest lucru reimplementând metoda respectivă, cu aceeași semnătură, în clasa derivată. Acest mecanism se numește ascundere (hiding):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;39-41&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    animal.makeSound();&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    cat.makeSound();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Polimorfismul =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Polimorfismul -- din greacă &amp;quot;poly&amp;quot; (mai multe) and &amp;quot;morphe&amp;quot; (forme) -- se referă la faptul că un obiect care este de tipul unei clase derivate, este în același timp și de tipul clasei de bază. Altfel spus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Dacă o clasă &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; extinde (direct sau indirect) o clasă &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;, atunci un obiect &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; de tipul &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; este în același timp și de tipul &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folosind acest concept, care este implementat și în limbajul C++, se pot utiliza pointeri sau referințe de un tip &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; pentru a referi obiecte de tipuri derivate din &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;50&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Animal Spot makes a sound!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Se vede că pe linia 50 de mai sus, avem o referință de tip &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; la un obiect de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;. Acest lucru este posibil pentru că o &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; este în același timp și un &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; (deoarece &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; extinde &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt;). Totuși, se poate observa din textul de ieșire că deși referințele &amp;lt;code&amp;gt;catRef&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;catRef2&amp;lt;/code&amp;gt; sunt către același obiect (de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;), apelul metodei &amp;lt;code&amp;gt;makeSound&amp;lt;/code&amp;gt; se face în funcție de tipul referinței, nu de tipul obiectului. Există însă scenarii în care se dorește comportamentul invers, anume apelul metodei în funcție de tipul obiectului, nu de tipul referinței cu care este accesat. Astfel, se introduce conceptul de &amp;#039;&amp;#039;&amp;#039;metodă virtuală&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
= Metode virtuale și suprascrierea metodelor =&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
Dacă o metodă este declarată virtuală, folosind cuvântul cheie &amp;lt;code&amp;gt;virtual&amp;lt;/code&amp;gt; plasat în fața tipului întors, atunci reimplementarea acesteia în clasele derivate se numește &amp;#039;&amp;#039;&amp;#039;suprascriere&amp;#039;&amp;#039;&amp;#039;. Apelul unei metode virtuale folosind o referință de alt tip decât al clasei din care face parte obiectul, va apela metoda corespunzătoare obiectului în sine, nu cea care aparține tipului referinței.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;15,39&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sfat&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;darkgreen&amp;quot;&amp;gt;Sfat:&amp;lt;/font&amp;gt; Când se suprascrie o metodă într-o clasă derivată, este recomandat să plasați înainte de acolada deschisă care implementează metoda cuvântul cheie &amp;lt;code&amp;gt;override&amp;lt;/code&amp;gt;. Deși acest lucru nu este obligatoriu, vă va avertiza printr-o eroare de compilare dacă suprascrierea nu se face corect (de exemplu dacă metoda din clasa de bază nu este declarată virtuală).&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Metode pur virtuale și clase abstracte =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
În anumite situații, o metodă virtuală nu poate avea o implementare în clasa de bază, pentru că nu este cunoscut modul în care aceasta se comportă. În această situație, metoda poate fi definită ca fiind &amp;#039;&amp;#039;&amp;#039;pur virtuală&amp;#039;&amp;#039;&amp;#039;, adică o metodă fără implementare, dar care este totuși declarată în cadrul clasei. Dacă o clasă conține cel puțin o metodă pur virtuală aceasta se numește &amp;#039;&amp;#039;&amp;#039;clasă abstractă&amp;#039;&amp;#039;&amp;#039; și nu poate fi instanțiată. Dacă am crea un obiect de tipul respectiv, atunci nu am putea apela metoda pur virtuală pentru că implementarea aceasteia lipsește. Clasele abstracte se pot folosi numai pentru a fi extinse, și metodele pur virtuale trebuie suprascrise în clasele derivate. Dacă cel puțin una din metodele pur virtuale nu este suprascrisă, atunci clasa derivată este la rândul ei abstractă.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual int getNumberOfLegs() const = 0;&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int getNumberOfLegs() const override {&lt;br /&gt;
        return 4;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;); // eroare de compilare, Animal este clasa abstracta&lt;br /&gt;
    &lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7364</id>
		<title>C++ POO Lab Lucrarea 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7364"/>
		<updated>2022-04-12T21:55:58Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Functii/Metode virtuale pure, clase abstracte */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Această lucrare are ca scop familiarizarea cu următoarele noțiuni:&lt;br /&gt;
&lt;br /&gt;
* Moștenirea&lt;br /&gt;
* Ascunderea metodelor&lt;br /&gt;
* Polimorfismul&lt;br /&gt;
* Metode virtuale și suprascrierea metodelor&lt;br /&gt;
* Metode pur virtuale și clase abstracte&lt;br /&gt;
&lt;br /&gt;
= Moștenirea =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Moștenirea este mecanismul prin care o clasă preia structura (câmpurile) și comportamentul (metodele) unei alte (sau mai multor) clase, la care poate adăuga alți membri specifici.&lt;br /&gt;
&lt;br /&gt;
Clasa de la care se preiau membrii se numește:&lt;br /&gt;
* clasă de bază&lt;br /&gt;
* superclasă&lt;br /&gt;
&lt;br /&gt;
Clasa nouă, care preia membrii de la clasa de bază se numește:&lt;br /&gt;
* clasă derivată&lt;br /&gt;
* clasă extinsă&lt;br /&gt;
* subclasă&lt;br /&gt;
&lt;br /&gt;
În C++, moștenirea poate fi multiplă, în sensul ca o clasa derivată poate moșteni mai multe clase de bază. Nu în toate limbajele există acest concept (în Java. de exemplu, există doar moștenire simplă - adică o clasă poate moșteni o singură altă clasă).&lt;br /&gt;
&lt;br /&gt;
Utilitatea moștenirii în programarea orientată pe obiecte este:&lt;br /&gt;
* reutilizarea codului existent fără modificarea acestuia;&lt;br /&gt;
* extinderea a unei clase deja scrise, fără a fi necesara recompilarea ei;&lt;br /&gt;
* utilizarea polimorfismului în timpul execuției, prin folosirea metodelor virtuale.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat() : mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Cat cat;&lt;br /&gt;
    cat.makeSound(); // makeSound este mostenita din clasa Animal&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În exemplul de mai sus, clasa &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; preia toți membrii din clasa &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; și adaugă un câmp &amp;lt;code&amp;gt;mLives&amp;lt;/code&amp;gt; și un constructor fără argumente. S-a introdus, de asemenea, un nou modificator de acces, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;, care permite accesul la membrul respectiv atât din clasa curentă cât și din orice clasă derivată din clasa curentă, dar nu și din alte clase sau funcții.&lt;br /&gt;
&lt;br /&gt;
Se observă, de asemenea, că moștenirea a fost declarată publică. Există două timpuri de moșteniri:&lt;br /&gt;
# publică&lt;br /&gt;
# privată&lt;br /&gt;
&lt;br /&gt;
Relativ la tipul de moștenire, mai jos este prezentat modul în care se preiau membrii din clasa de bază:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Accesul asupra membrilor moșteniți&lt;br /&gt;
|-&lt;br /&gt;
! Protecția in clasa de baza !! Modif de acces utilizat în lista claselor de bază !! Dreptul de acces în clasa derivată&lt;br /&gt;
|-&lt;br /&gt;
| public || public || public&lt;br /&gt;
|-&lt;br /&gt;
| private || public || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || public || protected&lt;br /&gt;
|-&lt;br /&gt;
| public || private || private&lt;br /&gt;
|-&lt;br /&gt;
| private || private || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || private || private&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;A doua diferență între &amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;struct&amp;lt;/code&amp;gt; este că pentru prima, moștenirea implicită este &amp;#039;&amp;#039;&amp;#039;private&amp;#039;&amp;#039;&amp;#039; iar pentru a doua este &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Apelul constructorului superclasei ==&lt;br /&gt;
&lt;br /&gt;
Când se instanțiază o clasă derivată, constructorul acestei clase se ocupă de inițializarea câmpurilor definite în clasa derivată. Pentru a inițializa câmpurile din clasa de bază, este necesar să apelăm constructorul ei. Prin urmare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Obligatoriu, constructorul unei clase derivate trebuie să apeleze constructorul clasei de bază. Dacă acest apel nu se face explicit, compilatorul va introduce un apel către constructorul clasei de bază fără argumente. Dacă acesta lipsește, apelul către constructorul clasei de bază trebuie făcut explicit, altfel se va genera o eroare de compilare.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apelul constructorului superclasei se face folosind aceeași sintaxă ca pentru inițializarea câmpurilor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;32&amp;quot;&amp;gt;&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ascunderea metodelor =&lt;br /&gt;
&lt;br /&gt;
În anumite situații, există nevoia ca o anumită metodă care este moștenită din clasa de bază să se comporte altfel în clasa derivată. Putem realiza acest lucru reimplementând metoda respectivă, cu aceeași semnătură, în clasa derivată. Acest mecanism se numește ascundere (hiding):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;39-41&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    animal.makeSound();&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    cat.makeSound();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Polimorfismul =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Polimorfismul -- din greacă &amp;quot;poly&amp;quot; (mai multe) and &amp;quot;morphe&amp;quot; (forme) -- se referă la faptul că un obiect care este de tipul unei clase derivate, este în același timp și de tipul clasei de bază. Altfel spus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Dacă o clasă &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; extinde (direct sau indirect) o clasă &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;, atunci un obiect &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; de tipul &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; este în același timp și de tipul &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folosind acest concept, care este implementat și în limbajul C++, se pot utiliza pointeri sau referințe de un tip &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; pentru a referi obiecte de tipuri derivate din &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;50&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Animal Spot makes a sound!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Se vede că pe linia 50 de mai sus, avem o referință de tip &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; la un obiect de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;. Acest lucru este posibil pentru că o &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; este în același timp și un &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; (deoarece &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; extinde &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt;). Totuși, se poate observa din textul de ieșire că deși referințele &amp;lt;code&amp;gt;catRef&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;catRef2&amp;lt;/code&amp;gt; sunt către același obiect (de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;), apelul metodei &amp;lt;code&amp;gt;makeSound&amp;lt;/code&amp;gt; se face în funcție de tipul referinței, nu de tipul obiectului. Există însă scenarii în care se dorește comportamentul invers, anume apelul metodei în funcție de tipul obiectului, nu de tipul referinței cu care este accesat. Astfel, se introduce conceptul de &amp;#039;&amp;#039;&amp;#039;metodă virtuală&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
= Metode virtuale și suprascrierea metodelor =&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
Dacă o metodă este declarată virtuală, folosind cuvântul cheie &amp;lt;code&amp;gt;virtual&amp;lt;/code&amp;gt; plasat în fața tipului întors, atunci reimplementarea acesteia în clasele derivate se numește &amp;#039;&amp;#039;&amp;#039;suprascriere&amp;#039;&amp;#039;&amp;#039;. Apelul unei metode virtuale folosind o referință de alt tip decât al clasei din care face parte obiectul, va apela metoda corespunzătoare obiectului în sine, nu cea care aparține tipului referinței.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;15,39&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sfat&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;darkgreen&amp;quot;&amp;gt;Sfat:&amp;lt;/font&amp;gt; Când se suprascrie o metodă într-o clasă derivată, este recomandat să plasați înainte de acolada deschisă care implementează metoda cuvântul cheie &amp;lt;code&amp;gt;override&amp;lt;/code&amp;gt;. Deși acest lucru nu este obligatoriu, vă va avertiza printr-o eroare de compilare dacă suprascrierea nu se face corect (de exemplu dacă metoda din clasa de bază nu este declarată virtuală).&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Metode pur virtuale și clase abstracte =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
În anumite situații, o metodă virtuală nu poate avea o implementare în clasa de bază, pentru că nu este cunoscut modul în care aceasta se comportă. În această situație, metoda poate fi definită ca fiind &amp;#039;&amp;#039;&amp;#039;pur virtuală&amp;#039;&amp;#039;&amp;#039;, adică o metodă fără implementare, dar care este totuși declarată în cadrul clasei. Dacă o clasă conține cel puțin o metodă pur virtuală aceasta se numește &amp;#039;&amp;#039;&amp;#039;clasă abstractă&amp;#039;&amp;#039;&amp;#039; și nu poate fi instanțiată. Dacă am crea un obiect de tipul respectiv, atunci nu am putea apela metoda pur virtuală pentru că implementarea aceasteia lipsește. Clasele abstracte se pot folosi numai pentru a fi extinse, și metodele pur virtuale trebuie suprascrise în clasele derivate. Dacă cel puțin una din metodele pur virtuale nu este suprascrisă, atunci clasa derivată este la rândul ei abstractă.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual int getNumberOfLegs() const = 0;&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int getNumberOfLegs() const override {&lt;br /&gt;
        return 4;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;); // eroare de compilare, Animal este clasa abstracta&lt;br /&gt;
    &lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7363</id>
		<title>C++ POO Lab Lucrarea 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7363"/>
		<updated>2022-04-12T21:43:56Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Exemplu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Această lucrare are ca scop familiarizarea cu următoarele noțiuni:&lt;br /&gt;
&lt;br /&gt;
* Moștenirea&lt;br /&gt;
* Ascunderea metodelor&lt;br /&gt;
* Polimorfismul&lt;br /&gt;
* Metode virtuale și suprascrierea metodelor&lt;br /&gt;
* Metode pur virtuale și clase abstracte&lt;br /&gt;
&lt;br /&gt;
= Moștenirea =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Moștenirea este mecanismul prin care o clasă preia structura (câmpurile) și comportamentul (metodele) unei alte (sau mai multor) clase, la care poate adăuga alți membri specifici.&lt;br /&gt;
&lt;br /&gt;
Clasa de la care se preiau membrii se numește:&lt;br /&gt;
* clasă de bază&lt;br /&gt;
* superclasă&lt;br /&gt;
&lt;br /&gt;
Clasa nouă, care preia membrii de la clasa de bază se numește:&lt;br /&gt;
* clasă derivată&lt;br /&gt;
* clasă extinsă&lt;br /&gt;
* subclasă&lt;br /&gt;
&lt;br /&gt;
În C++, moștenirea poate fi multiplă, în sensul ca o clasa derivată poate moșteni mai multe clase de bază. Nu în toate limbajele există acest concept (în Java. de exemplu, există doar moștenire simplă - adică o clasă poate moșteni o singură altă clasă).&lt;br /&gt;
&lt;br /&gt;
Utilitatea moștenirii în programarea orientată pe obiecte este:&lt;br /&gt;
* reutilizarea codului existent fără modificarea acestuia;&lt;br /&gt;
* extinderea a unei clase deja scrise, fără a fi necesara recompilarea ei;&lt;br /&gt;
* utilizarea polimorfismului în timpul execuției, prin folosirea metodelor virtuale.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat() : mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Cat cat;&lt;br /&gt;
    cat.makeSound(); // makeSound este mostenita din clasa Animal&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În exemplul de mai sus, clasa &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; preia toți membrii din clasa &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; și adaugă un câmp &amp;lt;code&amp;gt;mLives&amp;lt;/code&amp;gt; și un constructor fără argumente. S-a introdus, de asemenea, un nou modificator de acces, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;, care permite accesul la membrul respectiv atât din clasa curentă cât și din orice clasă derivată din clasa curentă, dar nu și din alte clase sau funcții.&lt;br /&gt;
&lt;br /&gt;
Se observă, de asemenea, că moștenirea a fost declarată publică. Există două timpuri de moșteniri:&lt;br /&gt;
# publică&lt;br /&gt;
# privată&lt;br /&gt;
&lt;br /&gt;
Relativ la tipul de moștenire, mai jos este prezentat modul în care se preiau membrii din clasa de bază:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Accesul asupra membrilor moșteniți&lt;br /&gt;
|-&lt;br /&gt;
! Protecția in clasa de baza !! Modif de acces utilizat în lista claselor de bază !! Dreptul de acces în clasa derivată&lt;br /&gt;
|-&lt;br /&gt;
| public || public || public&lt;br /&gt;
|-&lt;br /&gt;
| private || public || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || public || protected&lt;br /&gt;
|-&lt;br /&gt;
| public || private || private&lt;br /&gt;
|-&lt;br /&gt;
| private || private || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || private || private&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;A doua diferență între &amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;struct&amp;lt;/code&amp;gt; este că pentru prima, moștenirea implicită este &amp;#039;&amp;#039;&amp;#039;private&amp;#039;&amp;#039;&amp;#039; iar pentru a doua este &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Apelul constructorului superclasei ==&lt;br /&gt;
&lt;br /&gt;
Când se instanțiază o clasă derivată, constructorul acestei clase se ocupă de inițializarea câmpurilor definite în clasa derivată. Pentru a inițializa câmpurile din clasa de bază, este necesar să apelăm constructorul ei. Prin urmare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Obligatoriu, constructorul unei clase derivate trebuie să apeleze constructorul clasei de bază. Dacă acest apel nu se face explicit, compilatorul va introduce un apel către constructorul clasei de bază fără argumente. Dacă acesta lipsește, apelul către constructorul clasei de bază trebuie făcut explicit, altfel se va genera o eroare de compilare.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apelul constructorului superclasei se face folosind aceeași sintaxă ca pentru inițializarea câmpurilor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;32&amp;quot;&amp;gt;&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ascunderea metodelor =&lt;br /&gt;
&lt;br /&gt;
În anumite situații, există nevoia ca o anumită metodă care este moștenită din clasa de bază să se comporte altfel în clasa derivată. Putem realiza acest lucru reimplementând metoda respectivă, cu aceeași semnătură, în clasa derivată. Acest mecanism se numește ascundere (hiding):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;39-41&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    animal.makeSound();&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    cat.makeSound();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Polimorfismul =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Polimorfismul -- din greacă &amp;quot;poly&amp;quot; (mai multe) and &amp;quot;morphe&amp;quot; (forme) -- se referă la faptul că un obiect care este de tipul unei clase derivate, este în același timp și de tipul clasei de bază. Altfel spus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Dacă o clasă &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; extinde (direct sau indirect) o clasă &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;, atunci un obiect &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; de tipul &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; este în același timp și de tipul &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folosind acest concept, care este implementat și în limbajul C++, se pot utiliza pointeri sau referințe de un tip &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; pentru a referi obiecte de tipuri derivate din &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;50&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Animal Spot makes a sound!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Se vede că pe linia 50 de mai sus, avem o referință de tip &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; la un obiect de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;. Acest lucru este posibil pentru că o &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; este în același timp și un &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; (deoarece &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; extinde &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt;). Totuși, se poate observa din textul de ieșire că deși referințele &amp;lt;code&amp;gt;catRef&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;catRef2&amp;lt;/code&amp;gt; sunt către același obiect (de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;), apelul metodei &amp;lt;code&amp;gt;makeSound&amp;lt;/code&amp;gt; se face în funcție de tipul referinței, nu de tipul obiectului. Există însă scenarii în care se dorește comportamentul invers, anume apelul metodei în funcție de tipul obiectului, nu de tipul referinței cu care este accesat. Astfel, se introduce conceptul de &amp;#039;&amp;#039;&amp;#039;metodă virtuală&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
= Metode virtuale și suprascrierea metodelor =&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
Dacă o metodă este declarată virtuală, folosind cuvântul cheie &amp;lt;code&amp;gt;virtual&amp;lt;/code&amp;gt; plasat în fața tipului întors, atunci reimplementarea acesteia în clasele derivate se numește &amp;#039;&amp;#039;&amp;#039;suprascriere&amp;#039;&amp;#039;&amp;#039;. Apelul unei metode virtuale folosind o referință de alt tip decât al clasei din care face parte obiectul, va apela metoda corespunzătoare obiectului în sine, nu cea care aparține tipului referinței.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;15,39&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sfat&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;darkgreen&amp;quot;&amp;gt;Sfat:&amp;lt;/font&amp;gt; Când se suprascrie o metodă într-o clasă derivată, este recomandat să plasați înainte de acolada deschisă care implementează metoda cuvântul cheie &amp;lt;code&amp;gt;override&amp;lt;/code&amp;gt;. Deși acest lucru nu este obligatoriu, vă va avertiza printr-o eroare de compilare dacă suprascrierea nu se face corect (de exemplu dacă metoda din clasa de bază nu este declarată virtuală).&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Functii/Metode virtuale pure, clase abstracte =&lt;br /&gt;
&lt;br /&gt;
- o functie/metoda virtuala pura este o functie/metoda care nu are corp (body), nici macar gol&lt;br /&gt;
&lt;br /&gt;
virtual std::string toString() {}; // nu este o functie/metoda virtuala pura, are corp&lt;br /&gt;
&lt;br /&gt;
virtual std::string toString() = 0; // este o functie/metoda virtuala pura&lt;br /&gt;
&lt;br /&gt;
O clasa abstracta este o clasa care contine cel putin o metoda virtuala pura, si deci nu se poate instantia (nu exista obiecte de tip clasa &lt;br /&gt;
&lt;br /&gt;
Exemplu (pentru o clasa mostenita din clasa Animal de mai sus)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
class Pisica : public Animal {&lt;br /&gt;
public:&lt;br /&gt;
    Pisica() : Animal() // constructorul implicit Animal este chemat explicit&lt;br /&gt;
    { &lt;br /&gt;
      mHasFeathers = false;&lt;br /&gt;
    } // campul mHasFeathers este protected in Animal, deci poate fi accesat de Pisica &lt;br /&gt;
}; // nu uitati de ; la sfarsitul unei clase&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7362</id>
		<title>C++ POO Lab Lucrarea 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7362"/>
		<updated>2022-04-12T21:43:21Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Introducere */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Această lucrare are ca scop familiarizarea cu următoarele noțiuni:&lt;br /&gt;
&lt;br /&gt;
* Moștenirea&lt;br /&gt;
* Ascunderea metodelor&lt;br /&gt;
* Polimorfismul&lt;br /&gt;
* Metode virtuale și suprascrierea metodelor&lt;br /&gt;
* Metode pur virtuale și clase abstracte&lt;br /&gt;
&lt;br /&gt;
= Moștenirea =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Moștenirea este mecanismul prin care o clasă preia structura (câmpurile) și comportamentul (metodele) unei alte (sau mai multor) clase, la care poate adăuga alți membri specifici.&lt;br /&gt;
&lt;br /&gt;
Clasa de la care se preiau membrii se numește:&lt;br /&gt;
* clasă de bază&lt;br /&gt;
* superclasă&lt;br /&gt;
&lt;br /&gt;
Clasa nouă, care preia membrii de la clasa de bază se numește:&lt;br /&gt;
* clasă derivată&lt;br /&gt;
* clasă extinsă&lt;br /&gt;
* subclasă&lt;br /&gt;
&lt;br /&gt;
În C++, moștenirea poate fi multiplă, în sensul ca o clasa derivată poate moșteni mai multe clase de bază. Nu în toate limbajele există acest concept (în Java. de exemplu, există doar moștenire simplă - adică o clasă poate moșteni o singură altă clasă).&lt;br /&gt;
&lt;br /&gt;
Utilitatea moștenirii în programarea orientată pe obiecte este:&lt;br /&gt;
* reutilizarea codului existent fără modificarea acestuia;&lt;br /&gt;
* extinderea a unei clase deja scrise, fără a fi necesara recompilarea ei;&lt;br /&gt;
* utilizarea polimorfismului în timpul execuției, prin folosirea metodelor virtuale.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat() : mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Cat cat;&lt;br /&gt;
    cat.makeSound(); // makeSound este mostenita din clasa Animal&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În exemplul de mai sus, clasa &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; preia toți membrii din clasa &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; și adaugă un câmp &amp;lt;code&amp;gt;mLives&amp;lt;/code&amp;gt; și un constructor fără argumente. S-a introdus, de asemenea, un nou modificator de acces, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;, care permite accesul la membrul respectiv atât din clasa curentă cât și din orice clasă derivată din clasa curentă, dar nu și din alte clase sau funcții.&lt;br /&gt;
&lt;br /&gt;
Se observă, de asemenea, că moștenirea a fost declarată publică. Există două timpuri de moșteniri:&lt;br /&gt;
# publică&lt;br /&gt;
# privată&lt;br /&gt;
&lt;br /&gt;
Relativ la tipul de moștenire, mai jos este prezentat modul în care se preiau membrii din clasa de bază:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Accesul asupra membrilor moșteniți&lt;br /&gt;
|-&lt;br /&gt;
! Protecția in clasa de baza !! Modif de acces utilizat în lista claselor de bază !! Dreptul de acces în clasa derivată&lt;br /&gt;
|-&lt;br /&gt;
| public || public || public&lt;br /&gt;
|-&lt;br /&gt;
| private || public || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || public || protected&lt;br /&gt;
|-&lt;br /&gt;
| public || private || private&lt;br /&gt;
|-&lt;br /&gt;
| private || private || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || private || private&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;A doua diferență între &amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;struct&amp;lt;/code&amp;gt; este că pentru prima, moștenirea implicită este &amp;#039;&amp;#039;&amp;#039;private&amp;#039;&amp;#039;&amp;#039; iar pentru a doua este &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Apelul constructorului superclasei ==&lt;br /&gt;
&lt;br /&gt;
Când se instanțiază o clasă derivată, constructorul acestei clase se ocupă de inițializarea câmpurilor definite în clasa derivată. Pentru a inițializa câmpurile din clasa de bază, este necesar să apelăm constructorul ei. Prin urmare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Obligatoriu, constructorul unei clase derivate trebuie să apeleze constructorul clasei de bază. Dacă acest apel nu se face explicit, compilatorul va introduce un apel către constructorul clasei de bază fără argumente. Dacă acesta lipsește, apelul către constructorul clasei de bază trebuie făcut explicit, altfel se va genera o eroare de compilare.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apelul constructorului superclasei se face folosind aceeași sintaxă ca pentru inițializarea câmpurilor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;32&amp;quot;&amp;gt;&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ascunderea metodelor =&lt;br /&gt;
&lt;br /&gt;
În anumite situații, există nevoia ca o anumită metodă care este moștenită din clasa de bază să se comporte altfel în clasa derivată. Putem realiza acest lucru reimplementând metoda respectivă, cu aceeași semnătură, în clasa derivată. Acest mecanism se numește ascundere (hiding):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;39-41&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    animal.makeSound();&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    cat.makeSound();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Polimorfismul =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Polimorfismul -- din greacă &amp;quot;poly&amp;quot; (mai multe) and &amp;quot;morphe&amp;quot; (forme) -- se referă la faptul că un obiect care este de tipul unei clase derivate, este în același timp și de tipul clasei de bază. Altfel spus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Dacă o clasă &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; extinde (direct sau indirect) o clasă &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;, atunci un obiect &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; de tipul &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; este în același timp și de tipul &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folosind acest concept, care este implementat și în limbajul C++, se pot utiliza pointeri sau referințe de un tip &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; pentru a referi obiecte de tipuri derivate din &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;50&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Animal Spot makes a sound!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Se vede că pe linia 50 de mai sus, avem o referință de tip &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; la un obiect de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;. Acest lucru este posibil pentru că o &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; este în același timp și un &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; (deoarece &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; extinde &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt;). Totuși, se poate observa din textul de ieșire că deși referințele &amp;lt;code&amp;gt;catRef&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;catRef2&amp;lt;/code&amp;gt; sunt către același obiect (de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;), apelul metodei &amp;lt;code&amp;gt;makeSound&amp;lt;/code&amp;gt; se face în funcție de tipul referinței, nu de tipul obiectului. Există însă scenarii în care se dorește comportamentul invers, anume apelul metodei în funcție de tipul obiectului, nu de tipul referinței cu care este accesat. Astfel, se introduce conceptul de &amp;#039;&amp;#039;&amp;#039;metodă virtuală&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
= Metode virtuale și suprascrierea metodelor =&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
Dacă o metodă este declarată virtuală, folosind cuvântul cheie &amp;lt;code&amp;gt;virtual&amp;lt;/code&amp;gt; plasat în fața tipului întors, atunci reimplementarea acesteia în clasele derivate se numește &amp;#039;&amp;#039;&amp;#039;suprascriere&amp;#039;&amp;#039;&amp;#039;. Apelul unei metode virtuale folosind o referință de alt tip decât al clasei din care face parte obiectul, va apela metoda corespunzătoare obiectului în sine, nu cea care aparține tipului referinței.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;50&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sfat&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;darkgreen&amp;quot;&amp;gt;Sfat:&amp;lt;/font&amp;gt; Când se suprascrie o metodă într-o clasă derivată, este recomandat să plasați înainte de acolada deschisă care implementează metoda cuvântul cheie &amp;lt;code&amp;gt;override&amp;lt;/code&amp;gt;. Deși acest lucru nu este obligatoriu, vă va avertiza printr-o eroare de compilare dacă suprascrierea nu se face corect (de exemplu dacă metoda din clasa de bază nu este declarată virtuală).&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Functii/Metode virtuale pure, clase abstracte =&lt;br /&gt;
&lt;br /&gt;
- o functie/metoda virtuala pura este o functie/metoda care nu are corp (body), nici macar gol&lt;br /&gt;
&lt;br /&gt;
virtual std::string toString() {}; // nu este o functie/metoda virtuala pura, are corp&lt;br /&gt;
&lt;br /&gt;
virtual std::string toString() = 0; // este o functie/metoda virtuala pura&lt;br /&gt;
&lt;br /&gt;
O clasa abstracta este o clasa care contine cel putin o metoda virtuala pura, si deci nu se poate instantia (nu exista obiecte de tip clasa &lt;br /&gt;
&lt;br /&gt;
Exemplu (pentru o clasa mostenita din clasa Animal de mai sus)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
class Pisica : public Animal {&lt;br /&gt;
public:&lt;br /&gt;
    Pisica() : Animal() // constructorul implicit Animal este chemat explicit&lt;br /&gt;
    { &lt;br /&gt;
      mHasFeathers = false;&lt;br /&gt;
    } // campul mHasFeathers este protected in Animal, deci poate fi accesat de Pisica &lt;br /&gt;
}; // nu uitati de ; la sfarsitul unei clase&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7361</id>
		<title>C++ POO Lab Lucrarea 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7361"/>
		<updated>2022-04-12T21:42:40Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Această lucrare are ca scop familiarizarea cu următoarele noțiuni:&lt;br /&gt;
&lt;br /&gt;
* Moștenirea&lt;br /&gt;
* Ascunderea metodelor&lt;br /&gt;
* Polimorfismul&lt;br /&gt;
* Metode virtuale și suprascrierea metodelor&lt;br /&gt;
* Metode pur virtuale și clase abstracte&lt;br /&gt;
&lt;br /&gt;
= Moștenirea =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Moștenirea este mecanismul prin care o clasă preia structura (câmpurile) și comportamentul (metodele) unei alte (sau mai multor) clase, la care poate adăuga alți membri specifici.&lt;br /&gt;
&lt;br /&gt;
Clasa de la care se preiau membrii se numește:&lt;br /&gt;
* clasă de bază&lt;br /&gt;
* superclasă&lt;br /&gt;
&lt;br /&gt;
Clasa nouă, care preia membrii de la clasa de bază se numește:&lt;br /&gt;
* clasă derivată&lt;br /&gt;
* clasă extinsă&lt;br /&gt;
* subclasă&lt;br /&gt;
&lt;br /&gt;
În C++, moștenirea poate fi multiplă, în sensul ca o clasa derivată poate moșteni mai multe clase de bază. Nu în toate limbajele există acest concept (în Java. de exemplu, există doar moștenire simplă - adică o clasă poate moșteni o singură altă clasă).&lt;br /&gt;
&lt;br /&gt;
Utilitatea moștenirii în programarea orientată pe obiecte este:&lt;br /&gt;
* reutilizarea codului existent fără modificarea acestuia;&lt;br /&gt;
* extinderea a unei clase deja scrise, fără a fi necesara recompilarea ei;&lt;br /&gt;
* utilizarea polimorfismului în timpul execuției, prin folosirea metodelor virtuale.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat() : mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Cat cat;&lt;br /&gt;
    cat.makeSound(); // makeSound este mostenita din clasa Animal&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În exemplul de mai sus, clasa &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; preia toți membrii din clasa &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; și adaugă un câmp &amp;lt;code&amp;gt;mLives&amp;lt;/code&amp;gt; și un constructor fără argumente. S-a introdus, de asemenea, un nou modificator de acces, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;, care permite accesul la membrul respectiv atât din clasa curentă cât și din orice clasă derivată din clasa curentă, dar nu și din alte clase sau funcții.&lt;br /&gt;
&lt;br /&gt;
Se observă, de asemenea, că moștenirea a fost declarată publică. Există două timpuri de moșteniri:&lt;br /&gt;
# publică&lt;br /&gt;
# privată&lt;br /&gt;
&lt;br /&gt;
Relativ la tipul de moștenire, mai jos este prezentat modul în care se preiau membrii din clasa de bază:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Accesul asupra membrilor moșteniți&lt;br /&gt;
|-&lt;br /&gt;
! Protecția in clasa de baza !! Modif de acces utilizat în lista claselor de bază !! Dreptul de acces în clasa derivată&lt;br /&gt;
|-&lt;br /&gt;
| public || public || public&lt;br /&gt;
|-&lt;br /&gt;
| private || public || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || public || protected&lt;br /&gt;
|-&lt;br /&gt;
| public || private || private&lt;br /&gt;
|-&lt;br /&gt;
| private || private || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || private || private&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;A doua diferență între &amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;struct&amp;lt;/code&amp;gt; este că pentru prima, moștenirea implicită este &amp;#039;&amp;#039;&amp;#039;private&amp;#039;&amp;#039;&amp;#039; iar pentru a doua este &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Apelul constructorului superclasei ==&lt;br /&gt;
&lt;br /&gt;
Când se instanțiază o clasă derivată, constructorul acestei clase se ocupă de inițializarea câmpurilor definite în clasa derivată. Pentru a inițializa câmpurile din clasa de bază, este necesar să apelăm constructorul ei. Prin urmare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Obligatoriu, constructorul unei clase derivate trebuie să apeleze constructorul clasei de bază. Dacă acest apel nu se face explicit, compilatorul va introduce un apel către constructorul clasei de bază fără argumente. Dacă acesta lipsește, apelul către constructorul clasei de bază trebuie făcut explicit, altfel se va genera o eroare de compilare.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apelul constructorului superclasei se face folosind aceeași sintaxă ca pentru inițializarea câmpurilor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;32&amp;quot;&amp;gt;&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ascunderea metodelor =&lt;br /&gt;
&lt;br /&gt;
În anumite situații, există nevoia ca o anumită metodă care este moștenită din clasa de bază să se comporte altfel în clasa derivată. Putem realiza acest lucru reimplementând metoda respectivă, cu aceeași semnătură, în clasa derivată. Acest mecanism se numește ascundere (hiding):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;39-41&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    animal.makeSound();&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    cat.makeSound();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Polimorfismul =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Polimorfismul -- din greacă &amp;quot;poly&amp;quot; (mai multe) and &amp;quot;morphe&amp;quot; (forme) -- se referă la faptul că un obiect care este de tipul unei clase derivate, este în același timp și de tipul clasei de bază. Altfel spus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Dacă o clasă &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; extinde (direct sau indirect) o clasă &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;, atunci un obiect &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; de tipul &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; este în același timp și de tipul &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folosind acest concept, care este implementat și în limbajul C++, se pot utiliza pointeri sau referințe de un tip &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; pentru a referi obiecte de tipuri derivate din &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;50&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Animal Spot makes a sound!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Se vede că pe linia 50 de mai sus, avem o referință de tip &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; la un obiect de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;. Acest lucru este posibil pentru că o &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; este în același timp și un &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; (deoarece &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; extinde &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt;). Totuși, se poate observa din textul de ieșire că deși referințele &amp;lt;code&amp;gt;catRef&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;catRef2&amp;lt;/code&amp;gt; sunt către același obiect (de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;), apelul metodei &amp;lt;code&amp;gt;makeSound&amp;lt;/code&amp;gt; se face în funcție de tipul referinței, nu de tipul obiectului. Există însă scenarii în care se dorește comportamentul invers, anume apelul metodei în funcție de tipul obiectului, nu de tipul referinței cu care este accesat. Astfel, se introduce conceptul de &amp;#039;&amp;#039;&amp;#039;metodă virtuală&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
= Metode virtuale și suprascrierea metodelor =&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
Dacă o metodă este declarată virtuală, folosind cuvântul cheie &amp;lt;code&amp;gt;virtual&amp;lt;/code&amp;gt; plasat în fața tipului întors, atunci reimplementarea acesteia în clasele derivate se numește &amp;#039;&amp;#039;&amp;#039;suprascriere&amp;#039;&amp;#039;&amp;#039;. Apelul unei metode virtuale folosind o referință de alt tip decât a clasei din care face parte obiectul, va apela metoda corespunzătoare obiectului în sine, nu cea care aparține tipului referinței.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;50&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    virtual void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const override {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;sfat&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;darkgreen&amp;quot;&amp;gt;Sfat:&amp;lt;/font&amp;gt; Când se suprascrie o metodă într-o clasă derivată, este recomandat să plasați înainte de acolada deschisă care implementează metoda cuvântul cheie &amp;lt;code&amp;gt;override&amp;lt;/code&amp;gt;. Deși acest lucru nu este obligatoriu, vă va avertiza printr-o eroare de compilare dacă suprascrierea nu se face corect (de exemplu dacă metoda din clasa de bază nu este declarată virtuală).&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Functii/Metode virtuale pure, clase abstracte =&lt;br /&gt;
&lt;br /&gt;
- o functie/metoda virtuala pura este o functie/metoda care nu are corp (body), nici macar gol&lt;br /&gt;
&lt;br /&gt;
virtual std::string toString() {}; // nu este o functie/metoda virtuala pura, are corp&lt;br /&gt;
&lt;br /&gt;
virtual std::string toString() = 0; // este o functie/metoda virtuala pura&lt;br /&gt;
&lt;br /&gt;
O clasa abstracta este o clasa care contine cel putin o metoda virtuala pura, si deci nu se poate instantia (nu exista obiecte de tip clasa &lt;br /&gt;
&lt;br /&gt;
Exemplu (pentru o clasa mostenita din clasa Animal de mai sus)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
class Pisica : public Animal {&lt;br /&gt;
public:&lt;br /&gt;
    Pisica() : Animal() // constructorul implicit Animal este chemat explicit&lt;br /&gt;
    { &lt;br /&gt;
      mHasFeathers = false;&lt;br /&gt;
    } // campul mHasFeathers este protected in Animal, deci poate fi accesat de Pisica &lt;br /&gt;
}; // nu uitati de ; la sfarsitul unei clase&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7360</id>
		<title>C++ POO Lab Lucrarea 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7360"/>
		<updated>2022-04-12T21:34:15Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Polimorfismul */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Această lucrare are ca scop familiarizarea cu următoarele noțiuni:&lt;br /&gt;
&lt;br /&gt;
* Moștenirea&lt;br /&gt;
* Ascunderea metodelor&lt;br /&gt;
* Polimorfismul&lt;br /&gt;
* Metode virtuale&lt;br /&gt;
* Suprascrierea metodelor&lt;br /&gt;
* Metode pur virtuale&lt;br /&gt;
&lt;br /&gt;
= Moștenirea =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Moștenirea este mecanismul prin care o clasă preia structura (câmpurile) și comportamentul (metodele) unei alte (sau mai multor) clase, la care poate adăuga alți membri specifici.&lt;br /&gt;
&lt;br /&gt;
Clasa de la care se preiau membrii se numește:&lt;br /&gt;
* clasă de bază&lt;br /&gt;
* superclasă&lt;br /&gt;
&lt;br /&gt;
Clasa nouă, care preia membrii de la clasa de bază se numește:&lt;br /&gt;
* clasă derivată&lt;br /&gt;
* clasă extinsă&lt;br /&gt;
* subclasă&lt;br /&gt;
&lt;br /&gt;
În C++, moștenirea poate fi multiplă, în sensul ca o clasa derivată poate moșteni mai multe clase de bază. Nu în toate limbajele există acest concept (în Java. de exemplu, există doar moștenire simplă - adică o clasă poate moșteni o singură altă clasă).&lt;br /&gt;
&lt;br /&gt;
Utilitatea moștenirii în programarea orientată pe obiecte este:&lt;br /&gt;
* reutilizarea codului existent fără modificarea acestuia;&lt;br /&gt;
* extinderea a unei clase deja scrise, fără a fi necesara recompilarea ei;&lt;br /&gt;
* utilizarea polimorfismului în timpul execuției, prin folosirea metodelor virtuale.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat() : mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Cat cat;&lt;br /&gt;
    cat.makeSound(); // makeSound este mostenita din clasa Animal&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În exemplul de mai sus, clasa &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; preia toți membrii din clasa &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; și adaugă un câmp &amp;lt;code&amp;gt;mLives&amp;lt;/code&amp;gt; și un constructor fără argumente. S-a introdus, de asemenea, un nou modificator de acces, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;, care permite accesul la membrul respectiv atât din clasa curentă cât și din orice clasă derivată din clasa curentă, dar nu și din alte clase sau funcții.&lt;br /&gt;
&lt;br /&gt;
Se observă, de asemenea, că moștenirea a fost declarată publică. Există două timpuri de moșteniri:&lt;br /&gt;
# publică&lt;br /&gt;
# privată&lt;br /&gt;
&lt;br /&gt;
Relativ la tipul de moștenire, mai jos este prezentat modul în care se preiau membrii din clasa de bază:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Accesul asupra membrilor moșteniți&lt;br /&gt;
|-&lt;br /&gt;
! Protecția in clasa de baza !! Modif de acces utilizat în lista claselor de bază !! Dreptul de acces în clasa derivată&lt;br /&gt;
|-&lt;br /&gt;
| public || public || public&lt;br /&gt;
|-&lt;br /&gt;
| private || public || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || public || protected&lt;br /&gt;
|-&lt;br /&gt;
| public || private || private&lt;br /&gt;
|-&lt;br /&gt;
| private || private || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || private || private&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;A doua diferență între &amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;struct&amp;lt;/code&amp;gt; este că pentru prima, moștenirea implicită este &amp;#039;&amp;#039;&amp;#039;private&amp;#039;&amp;#039;&amp;#039; iar pentru a doua este &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Apelul constructorului superclasei ==&lt;br /&gt;
&lt;br /&gt;
Când se instanțiază o clasă derivată, constructorul acestei clase se ocupă de inițializarea câmpurilor definite în clasa derivată. Pentru a inițializa câmpurile din clasa de bază, este necesar să apelăm constructorul ei. Prin urmare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Obligatoriu, constructorul unei clase derivate trebuie să apeleze constructorul clasei de bază. Dacă acest apel nu se face explicit, compilatorul va introduce un apel către constructorul clasei de bază fără argumente. Dacă acesta lipsește, apelul către constructorul clasei de bază trebuie făcut explicit, altfel se va genera o eroare de compilare.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apelul constructorului superclasei se face folosind aceeași sintaxă ca pentru inițializarea câmpurilor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;32&amp;quot;&amp;gt;&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ascunderea metodelor =&lt;br /&gt;
&lt;br /&gt;
În anumite situații, există nevoia ca o anumită metodă care este moștenită din clasa de bază să se comporte altfel în clasa derivată. Putem realiza acest lucru reimplementând metoda respectivă, cu aceeași semnătură, în clasa derivată. Acest mecanism se numește ascundere (hiding):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;39-41&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    animal.makeSound();&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    cat.makeSound();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Polimorfismul =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Polimorfismul -- din greacă &amp;quot;poly&amp;quot; (mai multe) and &amp;quot;morphe&amp;quot; (forme) -- se referă la faptul că un obiect care este de tipul unei clase derivate, este în același timp și de tipul clasei de bază. Altfel spus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Dacă o clasă &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; extinde (direct sau indirect) o clasă &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;, atunci un obiect &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; de tipul &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; este în același timp și de tipul &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folosind acest concept, care este implementat și în limbajul C++, se pot utiliza pointeri sau referințe de un tip &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; pentru a referi obiecte de tipuri derivate din &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;50&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Animal Spot makes a sound!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Se vede că pe linia 50 de mai sus, avem o referință de tip &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; la un obiect de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;. Acest lucru este posibil pentru că o &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; este în același timp și un &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; (deoarece &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; extinde &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt;). Totuși, se poate observa din textul de ieșire că deși referințele &amp;lt;code&amp;gt;catRef&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;catRef2&amp;lt;/code&amp;gt; sunt către același obiect (de tip &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt;), apelul metodei &amp;lt;code&amp;gt;makeSound&amp;lt;/code&amp;gt; se face în funcție de tipul referinței, nu de tipul obiectului. Există însă scenarii în care se dorește comportamentul invers, anume apelul metodei în funcție de tipul obiectului, nu de tipul referinței cu care este accesat. Astfel, se introduce conceptul de &amp;#039;&amp;#039;&amp;#039;metodă virtuală&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
= Metode virtuale și suprascrierea metodelor =&lt;br /&gt;
== Introducere ==&lt;br /&gt;
&lt;br /&gt;
= Functii/Metode virtuale pure, clase abstracte =&lt;br /&gt;
&lt;br /&gt;
- o functie/metoda virtuala pura este o functie/metoda care nu are corp (body), nici macar gol&lt;br /&gt;
&lt;br /&gt;
virtual std::string toString() {}; // nu este o functie/metoda virtuala pura, are corp&lt;br /&gt;
&lt;br /&gt;
virtual std::string toString() = 0; // este o functie/metoda virtuala pura&lt;br /&gt;
&lt;br /&gt;
O clasa abstracta este o clasa care contine cel putin o metoda virtuala pura, si deci nu se poate instantia (nu exista obiecte de tip clasa &lt;br /&gt;
&lt;br /&gt;
Exemplu (pentru o clasa mostenita din clasa Animal de mai sus)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
class Pisica : public Animal {&lt;br /&gt;
public:&lt;br /&gt;
    Pisica() : Animal() // constructorul implicit Animal este chemat explicit&lt;br /&gt;
    { &lt;br /&gt;
      mHasFeathers = false;&lt;br /&gt;
    } // campul mHasFeathers este protected in Animal, deci poate fi accesat de Pisica &lt;br /&gt;
}; // nu uitati de ; la sfarsitul unei clase&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7359</id>
		<title>C++ POO Lab Lucrarea 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7359"/>
		<updated>2022-04-12T21:24:03Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Polimorfism */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Această lucrare are ca scop familiarizarea cu următoarele noțiuni:&lt;br /&gt;
&lt;br /&gt;
* Moștenirea&lt;br /&gt;
* Ascunderea metodelor&lt;br /&gt;
* Polimorfismul&lt;br /&gt;
* Metode virtuale&lt;br /&gt;
* Suprascrierea metodelor&lt;br /&gt;
* Metode pur virtuale&lt;br /&gt;
&lt;br /&gt;
= Moștenirea =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Moștenirea este mecanismul prin care o clasă preia structura (câmpurile) și comportamentul (metodele) unei alte (sau mai multor) clase, la care poate adăuga alți membri specifici.&lt;br /&gt;
&lt;br /&gt;
Clasa de la care se preiau membrii se numește:&lt;br /&gt;
* clasă de bază&lt;br /&gt;
* superclasă&lt;br /&gt;
&lt;br /&gt;
Clasa nouă, care preia membrii de la clasa de bază se numește:&lt;br /&gt;
* clasă derivată&lt;br /&gt;
* clasă extinsă&lt;br /&gt;
* subclasă&lt;br /&gt;
&lt;br /&gt;
În C++, moștenirea poate fi multiplă, în sensul ca o clasa derivată poate moșteni mai multe clase de bază. Nu în toate limbajele există acest concept (în Java. de exemplu, există doar moștenire simplă - adică o clasă poate moșteni o singură altă clasă).&lt;br /&gt;
&lt;br /&gt;
Utilitatea moștenirii în programarea orientată pe obiecte este:&lt;br /&gt;
* reutilizarea codului existent fără modificarea acestuia;&lt;br /&gt;
* extinderea a unei clase deja scrise, fără a fi necesara recompilarea ei;&lt;br /&gt;
* utilizarea polimorfismului în timpul execuției, prin folosirea metodelor virtuale.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat() : mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Cat cat;&lt;br /&gt;
    cat.makeSound(); // makeSound este mostenita din clasa Animal&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În exemplul de mai sus, clasa &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; preia toți membrii din clasa &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; și adaugă un câmp &amp;lt;code&amp;gt;mLives&amp;lt;/code&amp;gt; și un constructor fără argumente. S-a introdus, de asemenea, un nou modificator de acces, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;, care permite accesul la membrul respectiv atât din clasa curentă cât și din orice clasă derivată din clasa curentă, dar nu și din alte clase sau funcții.&lt;br /&gt;
&lt;br /&gt;
Se observă, de asemenea, că moștenirea a fost declarată publică. Există două timpuri de moșteniri:&lt;br /&gt;
# publică&lt;br /&gt;
# privată&lt;br /&gt;
&lt;br /&gt;
Relativ la tipul de moștenire, mai jos este prezentat modul în care se preiau membrii din clasa de bază:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Accesul asupra membrilor moșteniți&lt;br /&gt;
|-&lt;br /&gt;
! Protecția in clasa de baza !! Modif de acces utilizat în lista claselor de bază !! Dreptul de acces în clasa derivată&lt;br /&gt;
|-&lt;br /&gt;
| public || public || public&lt;br /&gt;
|-&lt;br /&gt;
| private || public || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || public || protected&lt;br /&gt;
|-&lt;br /&gt;
| public || private || private&lt;br /&gt;
|-&lt;br /&gt;
| private || private || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || private || private&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;A doua diferență între &amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;struct&amp;lt;/code&amp;gt; este că pentru prima, moștenirea implicită este &amp;#039;&amp;#039;&amp;#039;private&amp;#039;&amp;#039;&amp;#039; iar pentru a doua este &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Apelul constructorului superclasei ==&lt;br /&gt;
&lt;br /&gt;
Când se instanțiază o clasă derivată, constructorul acestei clase se ocupă de inițializarea câmpurilor definite în clasa derivată. Pentru a inițializa câmpurile din clasa de bază, este necesar să apelăm constructorul ei. Prin urmare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Obligatoriu, constructorul unei clase derivate trebuie să apeleze constructorul clasei de bază. Dacă acest apel nu se face explicit, compilatorul va introduce un apel către constructorul clasei de bază fără argumente. Dacă acesta lipsește, apelul către constructorul clasei de bază trebuie făcut explicit, altfel se va genera o eroare de compilare.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apelul constructorului superclasei se face folosind aceeași sintaxă ca pentru inițializarea câmpurilor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;32&amp;quot;&amp;gt;&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ascunderea metodelor =&lt;br /&gt;
&lt;br /&gt;
În anumite situații, există nevoia ca o anumită metodă care este moștenită din clasa de bază să se comporte altfel în clasa derivată. Putem realiza acest lucru reimplementând metoda respectivă, cu aceeași semnătură, în clasa derivată. Acest mecanism se numește ascundere (hiding):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;39-41&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    animal.makeSound();&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    cat.makeSound();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Polimorfismul =&lt;br /&gt;
&lt;br /&gt;
Polimorfismul -- din greacă &amp;quot;poly&amp;quot; (mai multe) and &amp;quot;morphe&amp;quot; (forme) -- se referă la faptul că un obiect care este de tipul unei clase derivate, este în același timp și de tipul clasei de bază. Altfel spus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Dacă o clasă &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; extinde (direct sau indirect) o clasă &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;, atunci un obiect &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; de tipul &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; este în același timp și de tipul &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folosind acest concept, care este implementat și în limbajul C++, se pot utiliza pointeri sau referințe de un tip &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; pentru a referi obiecte de tipuri derivate din &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    Animal &amp;amp; animalRef = animal;&lt;br /&gt;
    Cat &amp;amp; catRef = cat;&lt;br /&gt;
    Animal &amp;amp; catRef2 = cat;&lt;br /&gt;
&lt;br /&gt;
    animalRef.makeSound();&lt;br /&gt;
    catRef.makeSound();&lt;br /&gt;
    catRef2.makeSound();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
Animal Spot makes a sound!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Functii/Metode virtuale pure, clase abstracte =&lt;br /&gt;
&lt;br /&gt;
- o functie/metoda virtuala pura este o functie/metoda care nu are corp (body), nici macar gol&lt;br /&gt;
&lt;br /&gt;
virtual std::string toString() {}; // nu este o functie/metoda virtuala pura, are corp&lt;br /&gt;
&lt;br /&gt;
virtual std::string toString() = 0; // este o functie/metoda virtuala pura&lt;br /&gt;
&lt;br /&gt;
O clasa abstracta este o clasa care contine cel putin o metoda virtuala pura, si deci nu se poate instantia (nu exista obiecte de tip clasa &lt;br /&gt;
&lt;br /&gt;
Exemplu (pentru o clasa mostenita din clasa Animal de mai sus)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
class Pisica : public Animal {&lt;br /&gt;
public:&lt;br /&gt;
    Pisica() : Animal() // constructorul implicit Animal este chemat explicit&lt;br /&gt;
    { &lt;br /&gt;
      mHasFeathers = false;&lt;br /&gt;
    } // campul mHasFeathers este protected in Animal, deci poate fi accesat de Pisica &lt;br /&gt;
}; // nu uitati de ; la sfarsitul unei clase&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7358</id>
		<title>C++ POO Lab Lucrarea 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7358"/>
		<updated>2022-04-12T21:05:57Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Exemplu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Această lucrare are ca scop familiarizarea cu următoarele noțiuni:&lt;br /&gt;
&lt;br /&gt;
* Moștenirea&lt;br /&gt;
* Ascunderea metodelor&lt;br /&gt;
* Polimorfismul&lt;br /&gt;
* Metode virtuale&lt;br /&gt;
* Suprascrierea metodelor&lt;br /&gt;
* Metode pur virtuale&lt;br /&gt;
&lt;br /&gt;
= Moștenirea =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Moștenirea este mecanismul prin care o clasă preia structura (câmpurile) și comportamentul (metodele) unei alte (sau mai multor) clase, la care poate adăuga alți membri specifici.&lt;br /&gt;
&lt;br /&gt;
Clasa de la care se preiau membrii se numește:&lt;br /&gt;
* clasă de bază&lt;br /&gt;
* superclasă&lt;br /&gt;
&lt;br /&gt;
Clasa nouă, care preia membrii de la clasa de bază se numește:&lt;br /&gt;
* clasă derivată&lt;br /&gt;
* clasă extinsă&lt;br /&gt;
* subclasă&lt;br /&gt;
&lt;br /&gt;
În C++, moștenirea poate fi multiplă, în sensul ca o clasa derivată poate moșteni mai multe clase de bază. Nu în toate limbajele există acest concept (în Java. de exemplu, există doar moștenire simplă - adică o clasă poate moșteni o singură altă clasă).&lt;br /&gt;
&lt;br /&gt;
Utilitatea moștenirii în programarea orientată pe obiecte este:&lt;br /&gt;
* reutilizarea codului existent fără modificarea acestuia;&lt;br /&gt;
* extinderea a unei clase deja scrise, fără a fi necesara recompilarea ei;&lt;br /&gt;
* utilizarea polimorfismului în timpul execuției, prin folosirea metodelor virtuale.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat() : mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Cat cat;&lt;br /&gt;
    cat.makeSound(); // makeSound este mostenita din clasa Animal&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În exemplul de mai sus, clasa &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; preia toți membrii din clasa &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; și adaugă un câmp &amp;lt;code&amp;gt;mLives&amp;lt;/code&amp;gt; și un constructor fără argumente. S-a introdus, de asemenea, un nou modificator de acces, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;, care permite accesul la membrul respectiv atât din clasa curentă cât și din orice clasă derivată din clasa curentă, dar nu și din alte clase sau funcții.&lt;br /&gt;
&lt;br /&gt;
Se observă, de asemenea, că moștenirea a fost declarată publică. Există două timpuri de moșteniri:&lt;br /&gt;
# publică&lt;br /&gt;
# privată&lt;br /&gt;
&lt;br /&gt;
Relativ la tipul de moștenire, mai jos este prezentat modul în care se preiau membrii din clasa de bază:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Accesul asupra membrilor moșteniți&lt;br /&gt;
|-&lt;br /&gt;
! Protecția in clasa de baza !! Modif de acces utilizat în lista claselor de bază !! Dreptul de acces în clasa derivată&lt;br /&gt;
|-&lt;br /&gt;
| public || public || public&lt;br /&gt;
|-&lt;br /&gt;
| private || public || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || public || protected&lt;br /&gt;
|-&lt;br /&gt;
| public || private || private&lt;br /&gt;
|-&lt;br /&gt;
| private || private || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || private || private&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;A doua diferență între &amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;struct&amp;lt;/code&amp;gt; este că pentru prima, moștenirea implicită este &amp;#039;&amp;#039;&amp;#039;private&amp;#039;&amp;#039;&amp;#039; iar pentru a doua este &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Apelul constructorului superclasei ==&lt;br /&gt;
&lt;br /&gt;
Când se instanțiază o clasă derivată, constructorul acestei clase se ocupă de inițializarea câmpurilor definite în clasa derivată. Pentru a inițializa câmpurile din clasa de bază, este necesar să apelăm constructorul ei. Prin urmare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Obligatoriu, constructorul unei clase derivate trebuie să apeleze constructorul clasei de bază. Dacă acest apel nu se face explicit, compilatorul va introduce un apel către constructorul clasei de bază fără argumente. Dacă acesta lipsește, apelul către constructorul clasei de bază trebuie făcut explicit, altfel se va genera o eroare de compilare.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apelul constructorului superclasei se face folosind aceeași sintaxă ca pentru inițializarea câmpurilor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;32&amp;quot;&amp;gt;&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ascunderea metodelor =&lt;br /&gt;
&lt;br /&gt;
În anumite situații, există nevoia ca o anumită metodă care este moștenită din clasa de bază să se comporte altfel în clasa derivată. Putem realiza acest lucru reimplementând metoda respectivă, cu aceeași semnătură, în clasa derivată. Acest mecanism se numește ascundere (hiding):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;39-41&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    animal.makeSound();&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    cat.makeSound();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Polimorfism =&lt;br /&gt;
&lt;br /&gt;
Polimorfismul &amp;#039;&amp;#039;&amp;#039;parametric&amp;#039;&amp;#039;&amp;#039; – mecanismul prin care putem defini o metodă cu același nume în aceași clasă, funcții care trebuie să difere prin numărul și/sau tipul parametrilor și/sau ordinea lor. Selecția funcției se realizează la &amp;#039;&amp;#039;&amp;#039;compilare&amp;#039;&amp;#039;&amp;#039; (legarea timpurie (early binding)). Se numește foarte des &amp;#039;&amp;#039;&amp;#039;supraîncarcare&amp;#039;&amp;#039;&amp;#039; pentru a evita confuzia cu polimorfismul de moștenire.&lt;br /&gt;
&lt;br /&gt;
Polimorfismul &amp;#039;&amp;#039;&amp;#039;de moștenire&amp;#039;&amp;#039;&amp;#039; – mecanismul prin care o metodă din clasa de bază este redefinită cu aceiași semnatură (return value, nume, parametri) în clasele derivate. Selecția funcției se va realiza &amp;#039;&amp;#039;&amp;#039;la execuție&amp;#039;&amp;#039;&amp;#039; (legare întârziată == late binding). Acesta este sensul în care se folosește cel mai des, și deci sensul in care va fi interpretat cuvantul &amp;#039;&amp;#039;&amp;#039;polimorfism&amp;#039;&amp;#039;&amp;#039; (daca nu este specificat de ce tip este)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Avantaje&amp;#039;&amp;#039;&amp;#039;:&lt;br /&gt;
* clasa de baza si pointerul de tip clasa de baza pot fi scrise in codul sursa al unei biblioteci compilate cu mult timp inaintea compilarii clasei derivate (eg. ani de zile)&lt;br /&gt;
* pointerul de tip clasa de baza poate referi orice obiect, de orice tip clasa derivata a clasei de baza (și isi poate schimba dinamic valoarea, la execuție)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
private:&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers; // accesibil din eventualele clase derivate&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    virtual void makeSound() {&lt;br /&gt;
        std::cout &amp;lt;&amp;lt; &amp;quot;Animal &amp;quot; &amp;lt;&amp;lt; mName &amp;lt;&amp;lt; &amp;quot; makes a sound!&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void setName(std::string str) {&lt;br /&gt;
        mName = str;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Pisica : public Animal {&lt;br /&gt;
public:&lt;br /&gt;
    Pisica() : Animal() { mHasFeathers = false; }&lt;br /&gt;
&lt;br /&gt;
    // cuvantul &amp;#039;&amp;#039;&amp;#039;override&amp;#039;&amp;#039;&amp;#039; este optional dar recomandat si produce o eroare de compilare daca metoda makeSound din Pisica nu suprascrie metoda&lt;br /&gt;
    // makeSound din Animal din cauza unei erori de sintaxa (eg. nume usor schimbat, alt return type, alti parametri / ordine sau tip al lor&lt;br /&gt;
    void makeSound() override {&lt;br /&gt;
        std::cout &amp;lt;&amp;lt; &amp;quot;Pisica &amp;quot; &amp;lt;&amp;lt; getName() &amp;lt;&amp;lt; &amp;quot; makes a sound!&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // metoda din clasa Pisica ascunde implementarea din clasa Animal, dar nu o suprascrie polimorfic pentru ca setAge nu este virtuala in Animal&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if (age &amp;gt;= 20) std::cout &amp;lt;&amp;lt; &amp;quot;WARN: Longeviva pisica... sigur nu este o greseala?&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
&lt;br /&gt;
        Animal::setAge(age); // chemare setAge din clasa de baza Animal&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; std::endl &amp;lt;&amp;lt; &amp;quot;Demo Animal:&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    Animal *pAnimal;&lt;br /&gt;
    Animal un_animal;&lt;br /&gt;
    un_animal.setName(&amp;quot;TestoasaNinja&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    un_animal.makeSound(); // metoda makeSound din clasa Animal&lt;br /&gt;
    un_animal.setAge(99); // metoda setAge din clasa Animal&lt;br /&gt;
&lt;br /&gt;
    pAnimal = &amp;amp;un_animal;&lt;br /&gt;
    pAnimal-&amp;gt;makeSound(); // metoda makeSound din clasa Animal&lt;br /&gt;
    pAnimal-&amp;gt;setAge(99); // metoda setAge din clasa Animal&lt;br /&gt;
&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; std::endl &amp;lt;&amp;lt; &amp;quot;Demo Pisica:&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    Pisica tom;&lt;br /&gt;
    tom.setName(&amp;quot;Tom&amp;quot;);&lt;br /&gt;
    tom.makeSound(); // metoda makeSound din clasa Pisica&lt;br /&gt;
    tom.setAge(20); // metoda setAge din clasa Pisica&lt;br /&gt;
&lt;br /&gt;
    Pisica *pPisica;&lt;br /&gt;
    pPisica = &amp;amp;tom;&lt;br /&gt;
    pPisica-&amp;gt;makeSound(); // metoda makeSound din clasa Pisica&lt;br /&gt;
    pPisica-&amp;gt;setAge(20); // metoda setAge din clasa Pisica&lt;br /&gt;
&lt;br /&gt;
    // demonstratie POLIMORFISM (de mostenire):&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; std::endl &amp;lt;&amp;lt; &amp;quot;Demo Polimorfism (de mostenire):&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    pAnimal = &amp;amp;tom; // pointer de tip clasa de baza Animal, care contine o adresa de tip clasa derivata, Pisica&lt;br /&gt;
    pAnimal-&amp;gt;makeSound(); // ATENTIE: medoda makeSound din clasa Pisica (makeSound ESTE virtuala in clasa de baza Animal)&lt;br /&gt;
    pAnimal-&amp;gt;setAge(20); // ATENTIE: metoda setAge din clasa Animal (setAge NU este virtuala in clasa de baza Animal)&lt;br /&gt;
&lt;br /&gt;
    // pPisica = &amp;amp;un_animal; // eroare de compilare: invalid conversion from ‘Animal*’ to ‘Pisica*’ [-fpermissive]&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Secventa de mai sus afiseaza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
Demo Animal:&lt;br /&gt;
Animal TestoasaNinja makes a sound!&lt;br /&gt;
Animal TestoasaNinja makes a sound!&lt;br /&gt;
&lt;br /&gt;
Demo Pisica:&lt;br /&gt;
Pisica Tom makes a sound!&lt;br /&gt;
WARN: Longeviva pisica... sigur nu este o greseala?&lt;br /&gt;
Pisica Tom makes a sound!&lt;br /&gt;
WARN: Longeviva pisica... sigur nu este o greseala?&lt;br /&gt;
&lt;br /&gt;
Demo Polimorfism (de mostenire):&lt;br /&gt;
Pisica Tom makes a sound!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Functii/Metode virtuale pure, clase abstracte =&lt;br /&gt;
&lt;br /&gt;
- o functie/metoda virtuala pura este o functie/metoda care nu are corp (body), nici macar gol&lt;br /&gt;
&lt;br /&gt;
virtual std::string toString() {}; // nu este o functie/metoda virtuala pura, are corp&lt;br /&gt;
&lt;br /&gt;
virtual std::string toString() = 0; // este o functie/metoda virtuala pura&lt;br /&gt;
&lt;br /&gt;
O clasa abstracta este o clasa care contine cel putin o metoda virtuala pura, si deci nu se poate instantia (nu exista obiecte de tip clasa &lt;br /&gt;
&lt;br /&gt;
Exemplu (pentru o clasa mostenita din clasa Animal de mai sus)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
class Pisica : public Animal {&lt;br /&gt;
public:&lt;br /&gt;
    Pisica() : Animal() // constructorul implicit Animal este chemat explicit&lt;br /&gt;
    { &lt;br /&gt;
      mHasFeathers = false;&lt;br /&gt;
    } // campul mHasFeathers este protected in Animal, deci poate fi accesat de Pisica &lt;br /&gt;
}; // nu uitati de ; la sfarsitul unei clase&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7357</id>
		<title>C++ POO Lab Lucrarea 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7357"/>
		<updated>2022-04-12T21:05:16Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Ascunderea metodelor */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Această lucrare are ca scop familiarizarea cu următoarele noțiuni:&lt;br /&gt;
&lt;br /&gt;
* Moștenirea&lt;br /&gt;
* Ascunderea metodelor&lt;br /&gt;
* Polimorfismul&lt;br /&gt;
* Metode virtuale&lt;br /&gt;
* Suprascrierea metodelor&lt;br /&gt;
* Metode pur virtuale&lt;br /&gt;
&lt;br /&gt;
= Moștenirea =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Moștenirea este mecanismul prin care o clasă preia structura (câmpurile) și comportamentul (metodele) unei alte (sau mai multor) clase, la care poate adăuga alți membri specifici.&lt;br /&gt;
&lt;br /&gt;
Clasa de la care se preiau membrii se numește:&lt;br /&gt;
* clasă de bază&lt;br /&gt;
* superclasă&lt;br /&gt;
&lt;br /&gt;
Clasa nouă, care preia membrii de la clasa de bază se numește:&lt;br /&gt;
* clasă derivată&lt;br /&gt;
* clasă extinsă&lt;br /&gt;
* subclasă&lt;br /&gt;
&lt;br /&gt;
În C++, moștenirea poate fi multiplă, în sensul ca o clasa derivată poate moșteni mai multe clase de bază. Nu în toate limbajele există acest concept (în Java. de exemplu, există doar moștenire simplă - adică o clasă poate moșteni o singură altă clasă).&lt;br /&gt;
&lt;br /&gt;
Utilitatea moștenirii în programarea orientată pe obiecte este:&lt;br /&gt;
* reutilizarea codului existent fără modificarea acestuia;&lt;br /&gt;
* extinderea a unei clase deja scrise, fără a fi necesara recompilarea ei;&lt;br /&gt;
* utilizarea polimorfismului în timpul execuției, prin folosirea metodelor virtuale.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat() : mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Cat cat;&lt;br /&gt;
    cat.makeSound(); // makeSound este mostenita din clasa Animal&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În exemplul de mai sus, clasa &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; preia toți membrii din clasa &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; și adaugă un câmp &amp;lt;code&amp;gt;mLives&amp;lt;/code&amp;gt; și un constructor fără argumente. S-a introdus, de asemenea, un nou modificator de acces, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;, care permite accesul la membrul respectiv atât din clasa curentă cât și din orice clasă derivată din clasa curentă, dar nu și din alte clase sau funcții.&lt;br /&gt;
&lt;br /&gt;
Se observă, de asemenea, că moștenirea a fost declarată publică. Există două timpuri de moșteniri:&lt;br /&gt;
# publică&lt;br /&gt;
# privată&lt;br /&gt;
&lt;br /&gt;
Relativ la tipul de moștenire, mai jos este prezentat modul în care se preiau membrii din clasa de bază:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Accesul asupra membrilor moșteniți&lt;br /&gt;
|-&lt;br /&gt;
! Protecția in clasa de baza !! Modif de acces utilizat în lista claselor de bază !! Dreptul de acces în clasa derivată&lt;br /&gt;
|-&lt;br /&gt;
| public || public || public&lt;br /&gt;
|-&lt;br /&gt;
| private || public || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || public || protected&lt;br /&gt;
|-&lt;br /&gt;
| public || private || private&lt;br /&gt;
|-&lt;br /&gt;
| private || private || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || private || private&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;A doua diferență între &amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;struct&amp;lt;/code&amp;gt; este că pentru prima, moștenirea implicită este &amp;#039;&amp;#039;&amp;#039;private&amp;#039;&amp;#039;&amp;#039; iar pentru a doua este &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Apelul constructorului superclasei ==&lt;br /&gt;
&lt;br /&gt;
Când se instanțiază o clasă derivată, constructorul acestei clase se ocupă de inițializarea câmpurilor definite în clasa derivată. Pentru a inițializa câmpurile din clasa de bază, este necesar să apelăm constructorul ei. Prin urmare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Obligatoriu, constructorul unei clase derivate trebuie să apeleze constructorul clasei de bază. Dacă acest apel nu se face explicit, compilatorul va introduce un apel către constructorul clasei de bază fără argumente. Dacă acesta lipsește, apelul către constructorul clasei de bază trebuie făcut explicit, altfel se va genera o eroare de compilare.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apelul constructorului superclasei se face folosind aceeași sintaxă ca pentru inițializarea câmpurilor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;32&amp;quot;&amp;gt;&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ascunderea metodelor =&lt;br /&gt;
&lt;br /&gt;
În anumite situații, există nevoia ca o anumită metodă care este moștenită din clasa de bază să se comporte altfel în clasa derivată. Putem realiza acest lucru reimplementând metoda respectivă, cu aceeași semnătură, în clasa derivată. Acest mecanism se numește ascundere (hiding):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;39-41&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    animal.makeSound();&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    cat.makeSound();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Polimorfism =&lt;br /&gt;
&lt;br /&gt;
Polimorfismul &amp;#039;&amp;#039;&amp;#039;parametric&amp;#039;&amp;#039;&amp;#039; – mecanismul prin care putem defini o metodă cu același nume în aceași clasă, funcții care trebuie să difere prin numărul și/sau tipul parametrilor și/sau ordinea lor. Selecția funcției se realizează la &amp;#039;&amp;#039;&amp;#039;compilare&amp;#039;&amp;#039;&amp;#039; (legarea timpurie (early binding)). Se numește foarte des &amp;#039;&amp;#039;&amp;#039;supraîncarcare&amp;#039;&amp;#039;&amp;#039; pentru a evita confuzia cu polimorfismul de moștenire.&lt;br /&gt;
&lt;br /&gt;
Polimorfismul &amp;#039;&amp;#039;&amp;#039;de moștenire&amp;#039;&amp;#039;&amp;#039; – mecanismul prin care o metodă din clasa de bază este redefinită cu aceiași semnatură (return value, nume, parametri) în clasele derivate. Selecția funcției se va realiza &amp;#039;&amp;#039;&amp;#039;la execuție&amp;#039;&amp;#039;&amp;#039; (legare întârziată == late binding). Acesta este sensul în care se folosește cel mai des, și deci sensul in care va fi interpretat cuvantul &amp;#039;&amp;#039;&amp;#039;polimorfism&amp;#039;&amp;#039;&amp;#039; (daca nu este specificat de ce tip este)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Avantaje&amp;#039;&amp;#039;&amp;#039;:&lt;br /&gt;
* clasa de baza si pointerul de tip clasa de baza pot fi scrise in codul sursa al unei biblioteci compilate cu mult timp inaintea compilarii clasei derivate (eg. ani de zile)&lt;br /&gt;
* pointerul de tip clasa de baza poate referi orice obiect, de orice tip clasa derivata a clasei de baza (și isi poate schimba dinamic valoarea, la execuție)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
private:&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers; // accesibil din eventualele clase derivate&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    virtual void makeSound() {&lt;br /&gt;
        std::cout &amp;lt;&amp;lt; &amp;quot;Animal &amp;quot; &amp;lt;&amp;lt; mName &amp;lt;&amp;lt; &amp;quot; makes a sound!&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void setName(std::string str) {&lt;br /&gt;
        mName = str;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Pisica : public Animal {&lt;br /&gt;
public:&lt;br /&gt;
    Pisica() : Animal() { mHasFeathers = false; }&lt;br /&gt;
&lt;br /&gt;
    // cuvantul &amp;#039;&amp;#039;&amp;#039;override&amp;#039;&amp;#039;&amp;#039; este optional dar recomandat si produce o eroare de compilare daca metoda makeSound din Pisica nu suprascrie metoda&lt;br /&gt;
    // makeSound din Animal din cauza unei erori de sintaxa (eg. nume usor schimbat, alt return type, alti parametri / ordine sau tip al lor&lt;br /&gt;
    void makeSound() override {&lt;br /&gt;
        std::cout &amp;lt;&amp;lt; &amp;quot;Pisica &amp;quot; &amp;lt;&amp;lt; getName() &amp;lt;&amp;lt; &amp;quot; makes a sound!&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // metoda din clasa Pisica ascunde implementarea din clasa Animal, dar nu o suprascrie polimorfic pentru ca setAge nu este virtuala in Animal&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if (age &amp;gt;= 20) std::cout &amp;lt;&amp;lt; &amp;quot;WARN: Longeviva pisica... sigur nu este o greseala?&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
&lt;br /&gt;
        Animal::setAge(age); // chemare setAge din clasa de baza Animal&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; std::endl &amp;lt;&amp;lt; &amp;quot;Demo Animal:&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    Animal *pAnimal;&lt;br /&gt;
    Animal un_animal;&lt;br /&gt;
    un_animal.setName(&amp;quot;TestoasaNinja&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    un_animal.makeSound(); // metoda makeSound din clasa Animal&lt;br /&gt;
    un_animal.setAge(99); // metoda setAge din clasa Animal&lt;br /&gt;
&lt;br /&gt;
    pAnimal = &amp;amp;un_animal;&lt;br /&gt;
    pAnimal-&amp;gt;makeSound(); // metoda makeSound din clasa Animal&lt;br /&gt;
    pAnimal-&amp;gt;setAge(99); // metoda setAge din clasa Animal&lt;br /&gt;
&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; std::endl &amp;lt;&amp;lt; &amp;quot;Demo Pisica:&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    Pisica tom;&lt;br /&gt;
    tom.setName(&amp;quot;Tom&amp;quot;);&lt;br /&gt;
    tom.makeSound(); // metoda makeSound din clasa Pisica&lt;br /&gt;
    tom.setAge(20); // metoda setAge din clasa Pisica&lt;br /&gt;
&lt;br /&gt;
    Pisica *pPisica;&lt;br /&gt;
    pPisica = &amp;amp;tom;&lt;br /&gt;
    pPisica-&amp;gt;makeSound(); // metoda makeSound din clasa Pisica&lt;br /&gt;
    pPisica-&amp;gt;setAge(20); // metoda setAge din clasa Pisica&lt;br /&gt;
&lt;br /&gt;
    // demonstratie POLIMORFISM (de mostenire):&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; std::endl &amp;lt;&amp;lt; &amp;quot;Demo Polimorfism (de mostenire):&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    pAnimal = &amp;amp;tom; // pointer de tip clasa de baza Animal, care contine o adresa de tip clasa derivata, Pisica&lt;br /&gt;
    pAnimal-&amp;gt;makeSound(); // ATENTIE: medoda makeSound din clasa Pisica (makeSound ESTE virtuala in clasa de baza Animal)&lt;br /&gt;
    pAnimal-&amp;gt;setAge(20); // ATENTIE: metoda setAge din clasa Animal (setAge NU este virtuala in clasa de baza Animal)&lt;br /&gt;
&lt;br /&gt;
    // pPisica = &amp;amp;un_animal; // eroare de compilare: invalid conversion from ‘Animal*’ to ‘Pisica*’ [-fpermissive]&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Secventa de mai sus afiseaza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
Demo Animal:&lt;br /&gt;
Animal TestoasaNinja makes a sound!&lt;br /&gt;
Animal TestoasaNinja makes a sound!&lt;br /&gt;
&lt;br /&gt;
Demo Pisica:&lt;br /&gt;
Pisica Tom makes a sound!&lt;br /&gt;
WARN: Longeviva pisica... sigur nu este o greseala?&lt;br /&gt;
Pisica Tom makes a sound!&lt;br /&gt;
WARN: Longeviva pisica... sigur nu este o greseala?&lt;br /&gt;
&lt;br /&gt;
Demo Polimorfism (de mostenire):&lt;br /&gt;
Pisica Tom makes a sound!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Functii/Metode virtuale pure, clase abstracte =&lt;br /&gt;
&lt;br /&gt;
- o functie/metoda virtuala pura este o functie/metoda care nu are corp (body), nici macar gol&lt;br /&gt;
&lt;br /&gt;
virtual std::string toString() {}; // nu este o functie/metoda virtuala pura, are corp&lt;br /&gt;
&lt;br /&gt;
virtual std::string toString() = 0; // este o functie/metoda virtuala pura&lt;br /&gt;
&lt;br /&gt;
O clasa abstracta este o clasa care contine cel putin o metoda virtuala pura, si deci nu se poate instantia (nu exista obiecte de tip clasa &lt;br /&gt;
&lt;br /&gt;
Exemplu (pentru o clasa mostenita din clasa Animal de mai sus)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
class Pisica : public Animal {&lt;br /&gt;
public:&lt;br /&gt;
    Pisica() : Animal() // constructorul implicit Animal este chemat explicit&lt;br /&gt;
    { &lt;br /&gt;
      mHasFeathers = false;&lt;br /&gt;
    } // campul mHasFeathers este protected in Animal, deci poate fi accesat de Pisica &lt;br /&gt;
}; // nu uitati de ; la sfarsitul unei clase&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
	<entry>
		<id>http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7356</id>
		<title>C++ POO Lab Lucrarea 4</title>
		<link rel="alternate" type="text/html" href="http://wiki.dcae.pub.ro/index.php?title=C%2B%2B_POO_Lab_Lucrarea_4&amp;diff=7356"/>
		<updated>2022-04-12T21:04:47Z</updated>

		<summary type="html">&lt;p&gt;Rhobincu: /* Ascunderea metodelor */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Această lucrare are ca scop familiarizarea cu următoarele noțiuni:&lt;br /&gt;
&lt;br /&gt;
* Moștenirea&lt;br /&gt;
* Ascunderea metodelor&lt;br /&gt;
* Polimorfismul&lt;br /&gt;
* Metode virtuale&lt;br /&gt;
* Suprascrierea metodelor&lt;br /&gt;
* Metode pur virtuale&lt;br /&gt;
&lt;br /&gt;
= Moștenirea =&lt;br /&gt;
&lt;br /&gt;
== Introducere ==&lt;br /&gt;
Moștenirea este mecanismul prin care o clasă preia structura (câmpurile) și comportamentul (metodele) unei alte (sau mai multor) clase, la care poate adăuga alți membri specifici.&lt;br /&gt;
&lt;br /&gt;
Clasa de la care se preiau membrii se numește:&lt;br /&gt;
* clasă de bază&lt;br /&gt;
* superclasă&lt;br /&gt;
&lt;br /&gt;
Clasa nouă, care preia membrii de la clasa de bază se numește:&lt;br /&gt;
* clasă derivată&lt;br /&gt;
* clasă extinsă&lt;br /&gt;
* subclasă&lt;br /&gt;
&lt;br /&gt;
În C++, moștenirea poate fi multiplă, în sensul ca o clasa derivată poate moșteni mai multe clase de bază. Nu în toate limbajele există acest concept (în Java. de exemplu, există doar moștenire simplă - adică o clasă poate moșteni o singură altă clasă).&lt;br /&gt;
&lt;br /&gt;
Utilitatea moștenirii în programarea orientată pe obiecte este:&lt;br /&gt;
* reutilizarea codului existent fără modificarea acestuia;&lt;br /&gt;
* extinderea a unei clase deja scrise, fără a fi necesara recompilarea ei;&lt;br /&gt;
* utilizarea polimorfismului în timpul execuției, prin folosirea metodelor virtuale.&lt;br /&gt;
&lt;br /&gt;
== Exemplu ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat() : mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Cat cat;&lt;br /&gt;
    cat.makeSound(); // makeSound este mostenita din clasa Animal&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
În exemplul de mai sus, clasa &amp;lt;code&amp;gt;Cat&amp;lt;/code&amp;gt; preia toți membrii din clasa &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; și adaugă un câmp &amp;lt;code&amp;gt;mLives&amp;lt;/code&amp;gt; și un constructor fără argumente. S-a introdus, de asemenea, un nou modificator de acces, &amp;lt;code&amp;gt;protected&amp;lt;/code&amp;gt;, care permite accesul la membrul respectiv atât din clasa curentă cât și din orice clasă derivată din clasa curentă, dar nu și din alte clase sau funcții.&lt;br /&gt;
&lt;br /&gt;
Se observă, de asemenea, că moștenirea a fost declarată publică. Există două timpuri de moșteniri:&lt;br /&gt;
# publică&lt;br /&gt;
# privată&lt;br /&gt;
&lt;br /&gt;
Relativ la tipul de moștenire, mai jos este prezentat modul în care se preiau membrii din clasa de bază:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Accesul asupra membrilor moșteniți&lt;br /&gt;
|-&lt;br /&gt;
! Protecția in clasa de baza !! Modif de acces utilizat în lista claselor de bază !! Dreptul de acces în clasa derivată&lt;br /&gt;
|-&lt;br /&gt;
| public || public || public&lt;br /&gt;
|-&lt;br /&gt;
| private || public || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || public || protected&lt;br /&gt;
|-&lt;br /&gt;
| public || private || private&lt;br /&gt;
|-&lt;br /&gt;
| private || private || inaccesibil&lt;br /&gt;
|-&lt;br /&gt;
| protected || private || private&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;A doua diferență între &amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt; și &amp;lt;code&amp;gt;struct&amp;lt;/code&amp;gt; este că pentru prima, moștenirea implicită este &amp;#039;&amp;#039;&amp;#039;private&amp;#039;&amp;#039;&amp;#039; iar pentru a doua este &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Apelul constructorului superclasei ==&lt;br /&gt;
&lt;br /&gt;
Când se instanțiază o clasă derivată, constructorul acestei clase se ocupă de inițializarea câmpurilor definite în clasa derivată. Pentru a inițializa câmpurile din clasa de bază, este necesar să apelăm constructorul ei. Prin urmare:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;regula&amp;quot;&amp;gt;&amp;lt;font color=&amp;quot;#ff0000&amp;quot;&amp;gt;Atenție: &amp;lt;/font&amp;gt;Obligatoriu, constructorul unei clase derivate trebuie să apeleze constructorul clasei de bază. Dacă acest apel nu se face explicit, compilatorul va introduce un apel către constructorul clasei de bază fără argumente. Dacă acesta lipsește, apelul către constructorul clasei de bază trebuie făcut explicit, altfel se va genera o eroare de compilare.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Apelul constructorului superclasei se face folosind aceeași sintaxă ca pentru inițializarea câmpurilor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;32&amp;quot;&amp;gt;&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ascunderea metodelor =&lt;br /&gt;
&lt;br /&gt;
În anumite situații, există nevoia ca o anumită metodă care este moștenită din clasa de bază să se comporte altfel în clasa derivată. Putem realiza acest lucru reimplementând metoda respectivă, cu aceeași semnătură, în clasa derivată. Acest mecanism se numește ascundere (hiding):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot; line highlight=&amp;quot;36-38&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers;&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    Animal(const std::string &amp;amp; name, const std::string &amp;amp; color) : mName(name), mColor(color) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Animal %s makes a sound!\n&amp;quot;, mName.c_str());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() const {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Cat : public Animal {&lt;br /&gt;
    unsigned int mLives;&lt;br /&gt;
public:&lt;br /&gt;
    Cat(const std::string &amp;amp; name, const std::string &amp;amp; color) : Animal(name, color), mLives(9) {&lt;br /&gt;
        mHasFeathers = false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void makeSound() const {&lt;br /&gt;
        printf(&amp;quot;Cat %s meows!\n&amp;quot;, getName().c_str());&lt;br /&gt;
    }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Animal animal(&amp;quot;Rex&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
    animal.makeSound();&lt;br /&gt;
    Cat cat(&amp;quot;Spot&amp;quot;, &amp;quot;tabby&amp;quot;);&lt;br /&gt;
    cat.makeSound();&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ieșire:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Animal Rex makes a sound!&lt;br /&gt;
Cat Spot meows!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Polimorfism =&lt;br /&gt;
&lt;br /&gt;
Polimorfismul &amp;#039;&amp;#039;&amp;#039;parametric&amp;#039;&amp;#039;&amp;#039; – mecanismul prin care putem defini o metodă cu același nume în aceași clasă, funcții care trebuie să difere prin numărul și/sau tipul parametrilor și/sau ordinea lor. Selecția funcției se realizează la &amp;#039;&amp;#039;&amp;#039;compilare&amp;#039;&amp;#039;&amp;#039; (legarea timpurie (early binding)). Se numește foarte des &amp;#039;&amp;#039;&amp;#039;supraîncarcare&amp;#039;&amp;#039;&amp;#039; pentru a evita confuzia cu polimorfismul de moștenire.&lt;br /&gt;
&lt;br /&gt;
Polimorfismul &amp;#039;&amp;#039;&amp;#039;de moștenire&amp;#039;&amp;#039;&amp;#039; – mecanismul prin care o metodă din clasa de bază este redefinită cu aceiași semnatură (return value, nume, parametri) în clasele derivate. Selecția funcției se va realiza &amp;#039;&amp;#039;&amp;#039;la execuție&amp;#039;&amp;#039;&amp;#039; (legare întârziată == late binding). Acesta este sensul în care se folosește cel mai des, și deci sensul in care va fi interpretat cuvantul &amp;#039;&amp;#039;&amp;#039;polimorfism&amp;#039;&amp;#039;&amp;#039; (daca nu este specificat de ce tip este)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Avantaje&amp;#039;&amp;#039;&amp;#039;:&lt;br /&gt;
* clasa de baza si pointerul de tip clasa de baza pot fi scrise in codul sursa al unei biblioteci compilate cu mult timp inaintea compilarii clasei derivate (eg. ani de zile)&lt;br /&gt;
* pointerul de tip clasa de baza poate referi orice obiect, de orice tip clasa derivata a clasei de baza (și isi poate schimba dinamic valoarea, la execuție)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Animal {&lt;br /&gt;
private:&lt;br /&gt;
    std::string mName;&lt;br /&gt;
    std::string mColor;&lt;br /&gt;
    int mAge;&lt;br /&gt;
&lt;br /&gt;
protected:&lt;br /&gt;
    bool mHasFeathers; // accesibil din eventualele clase derivate&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    virtual void makeSound() {&lt;br /&gt;
        std::cout &amp;lt;&amp;lt; &amp;quot;Animal &amp;quot; &amp;lt;&amp;lt; mName &amp;lt;&amp;lt; &amp;quot; makes a sound!&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void setName(std::string str) {&lt;br /&gt;
        mName = str;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a getter method&lt;br /&gt;
    std::string getName() {&lt;br /&gt;
        return mName;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // this is a setter method&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if(age &amp;gt; 0) {&lt;br /&gt;
            mAge = age;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Pisica : public Animal {&lt;br /&gt;
public:&lt;br /&gt;
    Pisica() : Animal() { mHasFeathers = false; }&lt;br /&gt;
&lt;br /&gt;
    // cuvantul &amp;#039;&amp;#039;&amp;#039;override&amp;#039;&amp;#039;&amp;#039; este optional dar recomandat si produce o eroare de compilare daca metoda makeSound din Pisica nu suprascrie metoda&lt;br /&gt;
    // makeSound din Animal din cauza unei erori de sintaxa (eg. nume usor schimbat, alt return type, alti parametri / ordine sau tip al lor&lt;br /&gt;
    void makeSound() override {&lt;br /&gt;
        std::cout &amp;lt;&amp;lt; &amp;quot;Pisica &amp;quot; &amp;lt;&amp;lt; getName() &amp;lt;&amp;lt; &amp;quot; makes a sound!&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // metoda din clasa Pisica ascunde implementarea din clasa Animal, dar nu o suprascrie polimorfic pentru ca setAge nu este virtuala in Animal&lt;br /&gt;
    void setAge(int age) {&lt;br /&gt;
        if (age &amp;gt;= 20) std::cout &amp;lt;&amp;lt; &amp;quot;WARN: Longeviva pisica... sigur nu este o greseala?&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
&lt;br /&gt;
        Animal::setAge(age); // chemare setAge din clasa de baza Animal&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; std::endl &amp;lt;&amp;lt; &amp;quot;Demo Animal:&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    Animal *pAnimal;&lt;br /&gt;
    Animal un_animal;&lt;br /&gt;
    un_animal.setName(&amp;quot;TestoasaNinja&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    un_animal.makeSound(); // metoda makeSound din clasa Animal&lt;br /&gt;
    un_animal.setAge(99); // metoda setAge din clasa Animal&lt;br /&gt;
&lt;br /&gt;
    pAnimal = &amp;amp;un_animal;&lt;br /&gt;
    pAnimal-&amp;gt;makeSound(); // metoda makeSound din clasa Animal&lt;br /&gt;
    pAnimal-&amp;gt;setAge(99); // metoda setAge din clasa Animal&lt;br /&gt;
&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; std::endl &amp;lt;&amp;lt; &amp;quot;Demo Pisica:&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    Pisica tom;&lt;br /&gt;
    tom.setName(&amp;quot;Tom&amp;quot;);&lt;br /&gt;
    tom.makeSound(); // metoda makeSound din clasa Pisica&lt;br /&gt;
    tom.setAge(20); // metoda setAge din clasa Pisica&lt;br /&gt;
&lt;br /&gt;
    Pisica *pPisica;&lt;br /&gt;
    pPisica = &amp;amp;tom;&lt;br /&gt;
    pPisica-&amp;gt;makeSound(); // metoda makeSound din clasa Pisica&lt;br /&gt;
    pPisica-&amp;gt;setAge(20); // metoda setAge din clasa Pisica&lt;br /&gt;
&lt;br /&gt;
    // demonstratie POLIMORFISM (de mostenire):&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; std::endl &amp;lt;&amp;lt; &amp;quot;Demo Polimorfism (de mostenire):&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    pAnimal = &amp;amp;tom; // pointer de tip clasa de baza Animal, care contine o adresa de tip clasa derivata, Pisica&lt;br /&gt;
    pAnimal-&amp;gt;makeSound(); // ATENTIE: medoda makeSound din clasa Pisica (makeSound ESTE virtuala in clasa de baza Animal)&lt;br /&gt;
    pAnimal-&amp;gt;setAge(20); // ATENTIE: metoda setAge din clasa Animal (setAge NU este virtuala in clasa de baza Animal)&lt;br /&gt;
&lt;br /&gt;
    // pPisica = &amp;amp;un_animal; // eroare de compilare: invalid conversion from ‘Animal*’ to ‘Pisica*’ [-fpermissive]&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Secventa de mai sus afiseaza:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
Demo Animal:&lt;br /&gt;
Animal TestoasaNinja makes a sound!&lt;br /&gt;
Animal TestoasaNinja makes a sound!&lt;br /&gt;
&lt;br /&gt;
Demo Pisica:&lt;br /&gt;
Pisica Tom makes a sound!&lt;br /&gt;
WARN: Longeviva pisica... sigur nu este o greseala?&lt;br /&gt;
Pisica Tom makes a sound!&lt;br /&gt;
WARN: Longeviva pisica... sigur nu este o greseala?&lt;br /&gt;
&lt;br /&gt;
Demo Polimorfism (de mostenire):&lt;br /&gt;
Pisica Tom makes a sound!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Functii/Metode virtuale pure, clase abstracte =&lt;br /&gt;
&lt;br /&gt;
- o functie/metoda virtuala pura este o functie/metoda care nu are corp (body), nici macar gol&lt;br /&gt;
&lt;br /&gt;
virtual std::string toString() {}; // nu este o functie/metoda virtuala pura, are corp&lt;br /&gt;
&lt;br /&gt;
virtual std::string toString() = 0; // este o functie/metoda virtuala pura&lt;br /&gt;
&lt;br /&gt;
O clasa abstracta este o clasa care contine cel putin o metoda virtuala pura, si deci nu se poate instantia (nu exista obiecte de tip clasa &lt;br /&gt;
&lt;br /&gt;
Exemplu (pentru o clasa mostenita din clasa Animal de mai sus)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
class Pisica : public Animal {&lt;br /&gt;
public:&lt;br /&gt;
    Pisica() : Animal() // constructorul implicit Animal este chemat explicit&lt;br /&gt;
    { &lt;br /&gt;
      mHasFeathers = false;&lt;br /&gt;
    } // campul mHasFeathers este protected in Animal, deci poate fi accesat de Pisica &lt;br /&gt;
}; // nu uitati de ; la sfarsitul unei clase&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rhobincu</name></author>
	</entry>
</feed>